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 * 12*45753Smckusick * from: Utah $Hdr: hpux_compat.c 1.3 90/09/17$ 1341486Smckusick * 14*45753Smckusick * @(#)hpux_compat.c 7.10 (Berkeley) 12/05/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Various HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2341486Smckusick #include "param.h" 2441486Smckusick #include "systm.h" 2544421Skarels #include "user.h" 2641486Smckusick #include "kernel.h" 2741486Smckusick #include "proc.h" 2841486Smckusick #include "buf.h" 2941486Smckusick #include "wait.h" 3041486Smckusick #include "file.h" 3141486Smckusick #include "vnode.h" 3241486Smckusick #include "ioctl.h" 3341486Smckusick #include "uio.h" 3441486Smckusick #include "ptrace.h" 3541486Smckusick #include "stat.h" 3641486Smckusick #include "syslog.h" 3741486Smckusick #include "malloc.h" 3841486Smckusick #include "mount.h" 3941486Smckusick #include "ipc.h" 4041486Smckusick 4141486Smckusick #include "machine/cpu.h" 4241486Smckusick #include "machine/reg.h" 4341486Smckusick #include "machine/psl.h" 4441486Smckusick #include "machine/vmparam.h" 4541486Smckusick #include "hpux.h" 4641486Smckusick #include "hpux_termio.h" 4741486Smckusick 4841486Smckusick #ifdef DEBUG 4941486Smckusick int unimpresponse = 0; 5041486Smckusick #endif 5141486Smckusick 5241486Smckusick /* SYS5 style UTSNAME info */ 5341486Smckusick struct hpuxutsname protoutsname = { 5441486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5541486Smckusick }; 5641486Smckusick 5741486Smckusick /* 6.0 and later style context */ 5841486Smckusick #ifdef FPCOPROC 5941486Smckusick char hpuxcontext[] = 6041486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6141486Smckusick #else 6241486Smckusick char hpuxcontext[] = 6341486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 6441486Smckusick #endif 6541486Smckusick 6641486Smckusick /* YP domainname */ 6741486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 6841486Smckusick int domainnamelen = 7; 6941486Smckusick 7041486Smckusick #define NERR 79 7141486Smckusick #define BERR 1000 7241486Smckusick 7341486Smckusick /* indexed by BSD errno */ 7441486Smckusick short bsdtohpuxerrnomap[NERR] = { 7541486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7641486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 7741486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 7841486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 7941486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8041486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8141486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8241486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 8341486Smckusick }; 8441486Smckusick 8543452Shibler notimp(p, uap, retval, code, nargs) 8643452Shibler struct proc *p; 8743452Shibler int *uap, *retval; 8843452Shibler int code, nargs; 8941486Smckusick { 9043452Shibler int error = 0; 9141486Smckusick #ifdef DEBUG 9243452Shibler register int *argp = uap; 9341486Smckusick extern char *hpuxsyscallnames[]; 9441486Smckusick 9541486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9641486Smckusick if (nargs) 9741486Smckusick while (nargs--) 9841486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 9941486Smckusick else 10041486Smckusick printf(")"); 10141486Smckusick printf("\n"); 10241486Smckusick switch (unimpresponse) { 10341486Smckusick case 0: 10443452Shibler error = nosys(p, uap, retval); 10541486Smckusick break; 10641486Smckusick case 1: 10743452Shibler error = EINVAL; 10841486Smckusick break; 10941486Smckusick } 11041486Smckusick #else 11143452Shibler error = nosys(p, uap, retval); 11241486Smckusick #endif 11343452Shibler uprintf("HP-UX system call %d not implemented\n", code); 11444421Skarels return (error); 11541486Smckusick } 11641486Smckusick 11741486Smckusick /* 11841486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 11941486Smckusick * (status pointer, options, rusage) into the kernel rather than 12042352Smckusick * handling it in the C library stub. We also need to map any 12142352Smckusick * termination signal from BSD to HPUX. 12241486Smckusick */ 12343452Shibler hpuxwait3(p, uap, retval) 12443452Shibler struct proc *p; 12543452Shibler struct args { 12641486Smckusick int *status; 12741486Smckusick int options; 12841486Smckusick int rusage; 12943452Shibler } *uap; 13043452Shibler int *retval; 13143452Shibler { 13241486Smckusick /* rusage pointer must be zero */ 13343452Shibler if (uap->rusage) 13444421Skarels return (EINVAL); 13541486Smckusick u.u_ar0[PS] = PSL_ALLCC; 13641486Smckusick u.u_ar0[R0] = uap->options; 13741486Smckusick u.u_ar0[R1] = uap->rusage; 13844421Skarels return (hpuxwait(p, uap, retval)); 13941486Smckusick } 14041486Smckusick 14143452Shibler hpuxwait(p, uap, retval) 14243452Shibler struct proc *p; 14343452Shibler struct args { 14443452Shibler int *status; 14543452Shibler } *uap; 14643452Shibler int *retval; 14741486Smckusick { 14843452Shibler int sig, *statp, error; 14941486Smckusick 15041486Smckusick statp = uap->status; /* owait clobbers first arg */ 15143452Shibler error = owait(p, uap, retval); 15241486Smckusick /* 15341486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 15441486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 15541486Smckusick */ 15643452Shibler if (error == ERESTART) 15743452Shibler error = EINTR; 15843452Shibler if (error) 15944421Skarels return (error); 16043452Shibler sig = retval[1] & 0xFF; 16141486Smckusick if (sig == WSTOPPED) { 16243452Shibler sig = (retval[1] >> 8) & 0xFF; 16343452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 16441486Smckusick } else if (sig) 16543452Shibler retval[1] = (retval[1] & 0xFF00) | 16641486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 16741486Smckusick if (statp) 16843452Shibler if (suword((caddr_t)statp, retval[1])) 16943452Shibler error = EFAULT; 17044421Skarels return (error); 17141486Smckusick } 17241486Smckusick 17343452Shibler hpuxwaitpid(p, uap, retval) 17443452Shibler struct proc *p; 17543452Shibler struct args { 17642352Smckusick int pid; 17742352Smckusick int *status; 17842352Smckusick int options; 17942352Smckusick struct rusage *rusage; /* wait4 arg */ 18043452Shibler } *uap; 18143452Shibler int *retval; 18243452Shibler { 18343452Shibler int sig, *statp, error; 18442352Smckusick 18542352Smckusick uap->rusage = 0; 18643452Shibler error = wait4(p, uap, retval); 18742352Smckusick /* 18842352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 18942352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 19042352Smckusick */ 19143452Shibler if (error == ERESTART) 19243452Shibler error = EINTR; 19343452Shibler if (error) 19444421Skarels return (error); 19543452Shibler sig = retval[1] & 0xFF; 19642352Smckusick if (sig == WSTOPPED) { 19743452Shibler sig = (retval[1] >> 8) & 0xFF; 19843452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 19942352Smckusick } else if (sig) 20043452Shibler retval[1] = (retval[1] & 0xFF00) | 20142352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 20242352Smckusick if (statp) 20343452Shibler if (suword((caddr_t)statp, retval[1])) 20443452Shibler error = EFAULT; 20544421Skarels return (error); 20642352Smckusick } 20742352Smckusick 20841486Smckusick /* 20941486Smckusick * Must remap some bits in the mode mask. 21041486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 21141486Smckusick * O_SYNCIO (0100000) is removed entirely. 21241486Smckusick */ 21343067Skarels hpuxopen(p, uap, retval) 21443067Skarels struct proc *p; 21543452Shibler register struct args { 21641486Smckusick char *fname; 21741486Smckusick int mode; 21841486Smckusick int crtmode; 21943067Skarels } *uap; 22043067Skarels int *retval; 22143067Skarels { 22241486Smckusick int mode; 22341486Smckusick 22441486Smckusick mode = uap->mode; 22541486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 22641486Smckusick if (mode & HPUXFCREAT) { 22741486Smckusick /* 22841486Smckusick * simulate the pre-NFS behavior that opening a 22941486Smckusick * file for READ+CREATE ignores the CREATE (unless 23041486Smckusick * EXCL is set in which case we will return the 23141486Smckusick * proper error). 23241486Smckusick */ 23341486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 23441486Smckusick uap->mode |= FCREAT; 23541486Smckusick } 23641486Smckusick if (mode & HPUXFTRUNC) 23741486Smckusick uap->mode |= FTRUNC; 23841486Smckusick if (mode & HPUXFEXCL) 23941486Smckusick uap->mode |= FEXCL; 24044421Skarels return (open(p, uap, retval)); 24141486Smckusick } 24241486Smckusick 24343452Shibler hpuxfcntl(p, uap, retval) 24443452Shibler struct proc *p; 24543452Shibler register struct args { 24641486Smckusick int fdes; 24741486Smckusick int cmd; 24841486Smckusick int arg; 24943452Shibler } *uap; 25043452Shibler int *retval; 25143452Shibler { 25243452Shibler int mode, error; 25341486Smckusick 25441486Smckusick switch (uap->cmd) { 25541486Smckusick case F_SETFL: 25641486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 25741486Smckusick break; 25841486Smckusick case F_GETFL: 25941486Smckusick case F_DUPFD: 26041486Smckusick case F_GETFD: 26141486Smckusick case F_SETFD: 26241486Smckusick break; 26341486Smckusick default: 26444421Skarels return (EINVAL); 26541486Smckusick } 26643452Shibler error = fcntl(p, uap, retval); 26743452Shibler if (error == 0 && uap->arg == F_GETFL) { 26843452Shibler mode = *retval; 26943452Shibler *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 27041486Smckusick if (mode & FCREAT) 27143452Shibler *retval |= HPUXFCREAT; 27241486Smckusick if (mode & FTRUNC) 27343452Shibler *retval |= HPUXFTRUNC; 27441486Smckusick if (mode & FEXCL) 27543452Shibler *retval |= HPUXFEXCL; 27641486Smckusick } 27744421Skarels return (error); 27841486Smckusick } 27941486Smckusick 28041486Smckusick /* 28141486Smckusick * Read and write should return a 0 count when an operation 28241486Smckusick * on a VNODE would block, not an error. Sockets appear to 28341486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 28441486Smckusick * not entirely correct, since the behavior is only defined 28541486Smckusick * for pipes and tty type devices. 28641486Smckusick */ 28743452Shibler hpuxread(p, uap, retval) 28843452Shibler struct proc *p; 28943452Shibler struct args { 29043452Shibler int fd; 29143452Shibler } *uap; 29243452Shibler int *retval; 29341486Smckusick { 29443452Shibler int error; 29541486Smckusick 29643452Shibler error = read(p, uap, retval); 29743452Shibler if (error == EWOULDBLOCK && 29841486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 29943452Shibler error = 0; 30043452Shibler *retval = 0; 30141486Smckusick } 30244421Skarels return (error); 30341486Smckusick } 30441486Smckusick 30543452Shibler hpuxwrite(p, uap, retval) 30643452Shibler struct proc *p; 30743452Shibler struct args { 30843452Shibler int fd; 30943452Shibler } *uap; 31043452Shibler int *retval; 31141486Smckusick { 31243452Shibler int error; 31341486Smckusick 31443452Shibler error = write(p, uap, retval); 31543452Shibler if (error == EWOULDBLOCK && 31641486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 31743452Shibler error = 0; 31843452Shibler *retval = 0; 31941486Smckusick } 32044421Skarels return (error); 32141486Smckusick } 32241486Smckusick 32343452Shibler hpuxreadv(p, uap, retval) 32443452Shibler struct proc *p; 32543452Shibler struct args { 32643452Shibler int fd; 32743452Shibler } *uap; 32843452Shibler int *retval; 32941486Smckusick { 33043452Shibler int error; 33141486Smckusick 33243452Shibler error = readv(p, uap, retval); 33343452Shibler if (error == EWOULDBLOCK && 33441486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 33543452Shibler error = 0; 33643452Shibler *retval = 0; 33741486Smckusick } 33844421Skarels return (error); 33941486Smckusick } 34041486Smckusick 34143452Shibler hpuxwritev(p, uap, retval) 34243452Shibler struct proc *p; 34343452Shibler struct args { 34443452Shibler int fd; 34543452Shibler } *uap; 34643452Shibler int *retval; 34741486Smckusick { 34843452Shibler int error; 34941486Smckusick 35043452Shibler error = writev(p, uap, retval); 35143452Shibler if (error == EWOULDBLOCK && 35241486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 35343452Shibler error = 0; 35443452Shibler *retval = 0; 35541486Smckusick } 35644421Skarels return (error); 35741486Smckusick } 35841486Smckusick 35941486Smckusick /* 36041486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 36141486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 36241486Smckusick */ 36343452Shibler hpuxdup(p, uap, retval) 36443452Shibler struct proc *p; 36543452Shibler register struct args { 36643452Shibler int i; 36743452Shibler } *uap; 36843452Shibler int *retval; 36941486Smckusick { 37041486Smckusick struct file *fp; 37143452Shibler int fd, error; 37241486Smckusick 37343452Shibler if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 37444421Skarels return (EBADF); 37543452Shibler if (error = ufalloc(0, &fd)) 37644421Skarels return (error); 37743452Shibler *retval = fd; 37843452Shibler u.u_ofile[fd] = fp; 37943452Shibler u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 38043067Skarels fp->f_count++; 38143452Shibler if (fd > u.u_lastfile) 38243452Shibler u.u_lastfile = fd; 38344421Skarels return (0); 38441486Smckusick } 38541486Smckusick 386*45753Smckusick hpuxutssys(p, uap, retval) 38743452Shibler struct proc *p; 38843452Shibler register struct args { 38941486Smckusick struct hpuxutsname *uts; 39041486Smckusick int dev; 39141486Smckusick int request; 39243452Shibler } *uap; 39343452Shibler int *retval; 39443452Shibler { 39541486Smckusick register int i; 39643452Shibler int error; 39741486Smckusick 39841486Smckusick switch (uap->request) { 39941486Smckusick /* uname */ 40041486Smckusick case 0: 40141486Smckusick /* fill in machine type */ 40241486Smckusick switch (machineid) { 40341486Smckusick case HP_320: 40441486Smckusick protoutsname.machine[6] = '2'; 40541486Smckusick break; 40641486Smckusick /* includes 318 and 319 */ 40741486Smckusick case HP_330: 40841486Smckusick protoutsname.machine[6] = '3'; 40941486Smckusick break; 41041486Smckusick case HP_340: 41141486Smckusick protoutsname.machine[6] = '4'; 41241486Smckusick break; 41341486Smckusick case HP_350: 41441486Smckusick protoutsname.machine[6] = '5'; 41541486Smckusick break; 41641486Smckusick case HP_360: 41741486Smckusick protoutsname.machine[6] = '6'; 41841486Smckusick break; 41941486Smckusick case HP_370: 42041486Smckusick protoutsname.machine[6] = '7'; 42141486Smckusick break; 42243452Shibler /* includes 345 */ 42343452Shibler case HP_375: 42443452Shibler protoutsname.machine[6] = '7'; 42543452Shibler protoutsname.machine[7] = '5'; 42643452Shibler break; 42741486Smckusick } 42841486Smckusick /* copy hostname (sans domain) to nodename */ 42941486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 43041486Smckusick protoutsname.nodename[i] = hostname[i]; 43143452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 43243452Shibler sizeof(struct hpuxutsname)); 43341486Smckusick break; 434*45753Smckusick 435*45753Smckusick /* gethostname */ 436*45753Smckusick case 5: 437*45753Smckusick /* uap->dev is length */ 438*45753Smckusick if (uap->dev > hostnamelen + 1) 439*45753Smckusick uap->dev = hostnamelen + 1; 440*45753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 441*45753Smckusick uap->dev); 442*45753Smckusick break; 443*45753Smckusick 444*45753Smckusick case 1: /* ?? */ 445*45753Smckusick case 2: /* ustat */ 446*45753Smckusick case 3: /* ?? */ 447*45753Smckusick case 4: /* sethostname */ 44841486Smckusick default: 44943452Shibler error = EINVAL; 45041486Smckusick break; 45141486Smckusick } 45244421Skarels return (error); 45341486Smckusick } 45441486Smckusick 45543452Shibler hpuxstat(p, uap, retval) 45643452Shibler struct proc *p; 45743452Shibler struct args { 45841486Smckusick char *fname; 45941486Smckusick struct hpuxstat *hsb; 46043452Shibler } *uap; 46143452Shibler int *retval; 46243452Shibler { 46344421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 46441486Smckusick } 46541486Smckusick 46643452Shibler hpuxlstat(p, uap, retval) 46743452Shibler struct proc *p; 46843452Shibler struct args { 46943452Shibler char *fname; 47043452Shibler struct hpuxstat *hsb; 47143452Shibler } *uap; 47243452Shibler int *retval; 47341486Smckusick { 47444421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 47541486Smckusick } 47641486Smckusick 47743452Shibler hpuxfstat(p, uap, retval) 47843452Shibler struct proc *p; 47943452Shibler register struct args { 48043452Shibler int fdes; 48143452Shibler struct hpuxstat *hsb; 48243452Shibler } *uap; 48343452Shibler int *retval; 48441486Smckusick { 48541486Smckusick register struct file *fp; 48641486Smckusick struct stat sb; 48743452Shibler int error; 48841486Smckusick 48941486Smckusick if ((unsigned)uap->fdes >= NOFILE || 49043452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 49144421Skarels return (EBADF); 49243452Shibler 49341486Smckusick switch (fp->f_type) { 49441486Smckusick 49541486Smckusick case DTYPE_VNODE: 49643452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 49741486Smckusick break; 49841486Smckusick 49941486Smckusick case DTYPE_SOCKET: 50043452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 50141486Smckusick break; 50241486Smckusick 50341486Smckusick default: 50441486Smckusick panic("fstat"); 50541486Smckusick /*NOTREACHED*/ 50641486Smckusick } 50741486Smckusick /* is this right for sockets?? */ 50843452Shibler if (error == 0) 50943452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 51044421Skarels return (error); 51141486Smckusick } 51241486Smckusick 51343452Shibler hpuxulimit(p, uap, retval) 51443452Shibler struct proc *p; 51543452Shibler register struct args { 51641486Smckusick int cmd; 51741486Smckusick long newlimit; 51843452Shibler } *uap; 51943713Smckusick off_t *retval; 52043452Shibler { 52141486Smckusick struct rlimit *limp; 52243452Shibler int error = 0; 52341486Smckusick 52441486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 52541486Smckusick switch (uap->cmd) { 52641486Smckusick case 2: 52741486Smckusick uap->newlimit *= 512; 52841486Smckusick if (uap->newlimit > limp->rlim_max && 52943452Shibler (error = suser(u.u_cred, &u.u_acflag))) 53041486Smckusick break; 53141486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 53241486Smckusick /* else fall into... */ 53341486Smckusick 53441486Smckusick case 1: 535*45753Smckusick *retval = limp->rlim_max / 512; 53641486Smckusick break; 53741486Smckusick 53841486Smckusick case 3: 53941486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 540*45753Smckusick *retval = ctob(u.u_tsize) + limp->rlim_max; 54141486Smckusick break; 54241486Smckusick 54341486Smckusick default: 54443452Shibler error = EINVAL; 54541486Smckusick break; 54641486Smckusick } 54744421Skarels return (error); 54841486Smckusick } 54941486Smckusick 55041486Smckusick /* 55141486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 55241486Smckusick * values -16 (high) thru -1 (low). 55341486Smckusick */ 55443452Shibler hpuxrtprio(cp, uap, retval) 55543452Shibler struct proc *cp; 55643452Shibler register struct args { 55741486Smckusick int pid; 55841486Smckusick int prio; 55943452Shibler } *uap; 56043452Shibler int *retval; 56143452Shibler { 56241486Smckusick struct proc *p; 56343452Shibler int nice, error; 56441486Smckusick 56541486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 56643452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 56744421Skarels return (EINVAL); 56841486Smckusick if (uap->pid == 0) 56943452Shibler p = cp; 57043452Shibler else if ((p = pfind(uap->pid)) == 0) 57144421Skarels return (ESRCH); 57241486Smckusick nice = p->p_nice; 57341486Smckusick if (nice < NZERO) 57443452Shibler *retval = (nice + 16) << 3; 57541486Smckusick else 57643452Shibler *retval = RTPRIO_RTOFF; 57741486Smckusick switch (uap->prio) { 57841486Smckusick 57941486Smckusick case RTPRIO_NOCHG: 58044421Skarels return (0); 58141486Smckusick 58241486Smckusick case RTPRIO_RTOFF: 58341486Smckusick if (nice >= NZERO) 58444421Skarels return (0); 58541486Smckusick nice = NZERO; 58641486Smckusick break; 58741486Smckusick 58841486Smckusick default: 58941486Smckusick nice = (uap->prio >> 3) - 16; 59041486Smckusick break; 59141486Smckusick } 59243452Shibler error = donice(cp, p, nice); 59343452Shibler if (error == EACCES) 59443452Shibler error = EPERM; 59544421Skarels return (error); 59641486Smckusick } 59741486Smckusick 59843452Shibler hpuxadvise(p, uap, retval) 59943452Shibler struct proc *p; 60043452Shibler struct args { 60143452Shibler int arg; 60243452Shibler } *uap; 60343452Shibler int *retval; 60441486Smckusick { 60543452Shibler int error = 0; 60641486Smckusick 60741486Smckusick switch (uap->arg) { 60841486Smckusick case 0: 60941486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 61041486Smckusick break; 61141486Smckusick case 1: 61241486Smckusick ICIA(); 61341486Smckusick break; 61441486Smckusick case 2: 61541486Smckusick DCIA(); 61641486Smckusick break; 61741486Smckusick default: 61843452Shibler error = EINVAL; 61941486Smckusick break; 62041486Smckusick } 62144421Skarels return (error); 62241486Smckusick } 62341486Smckusick 62443452Shibler hpuxptrace(p, uap, retval) 62543452Shibler struct proc *p; 62643452Shibler struct args { 62741486Smckusick int req; 62841486Smckusick int pid; 62941486Smckusick int *addr; 63041486Smckusick int data; 63143452Shibler } *uap; 63243452Shibler int *retval; 63343452Shibler { 63443452Shibler int error; 63541486Smckusick 63641486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 63741486Smckusick if (uap->data) { 63841486Smckusick uap->data = hpuxtobsdsig(uap->data); 63941486Smckusick if (uap->data == 0) 64041486Smckusick uap->data = NSIG; 64141486Smckusick } 64241486Smckusick } 64343452Shibler error = ptrace(p, uap, retval); 64444421Skarels return (error); 64541486Smckusick } 64641486Smckusick 64743452Shibler hpuxgetdomainname(p, uap, retval) 64843452Shibler struct proc *p; 64943452Shibler register struct args { 65041486Smckusick char *domainname; 65141486Smckusick u_int len; 65243452Shibler } *uap; 65343452Shibler int *retval; 65443452Shibler { 65541486Smckusick if (uap->len > domainnamelen + 1) 65641486Smckusick uap->len = domainnamelen + 1; 65744421Skarels return (copyout(domainname, uap->domainname, uap->len)); 65841486Smckusick } 65941486Smckusick 66043452Shibler hpuxsetdomainname(p, uap, retval) 66143452Shibler struct proc *p; 66243452Shibler register struct args { 66341486Smckusick char *domainname; 66441486Smckusick u_int len; 66543452Shibler } *uap; 66643452Shibler int *retval; 66743452Shibler { 66843452Shibler int error; 66941486Smckusick 67043452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 67144421Skarels return (error); 67243452Shibler if (uap->len > sizeof (domainname) - 1) 67344421Skarels return (EINVAL); 67441486Smckusick domainnamelen = uap->len; 67543452Shibler error = copyin(uap->domainname, domainname, uap->len); 67641486Smckusick domainname[domainnamelen] = 0; 67744421Skarels return (error); 67841486Smckusick } 67941486Smckusick 68041486Smckusick #ifdef SYSVSHM 68143452Shibler hpuxshmat(p, uap, retval) 68243452Shibler struct proc *p; 68343452Shibler int *uap, *retval; 68441486Smckusick { 68544421Skarels return (shmat(p, uap, retval)); 68641486Smckusick } 68741486Smckusick 68843452Shibler hpuxshmctl(p, uap, retval) 68943452Shibler struct proc *p; 69043452Shibler int *uap, *retval; 69141486Smckusick { 69244421Skarels return (shmctl(p, uap, retval)); 69341486Smckusick } 69441486Smckusick 69543452Shibler hpuxshmdt(p, uap, retval) 69643452Shibler struct proc *p; 69743452Shibler int *uap, *retval; 69841486Smckusick { 69944421Skarels return (shmdt(p, uap, retval)); 70041486Smckusick } 70141486Smckusick 70243452Shibler hpuxshmget(p, uap, retval) 70343452Shibler struct proc *p; 70443452Shibler int *uap, *retval; 70541486Smckusick { 70644421Skarels return (shmget(p, uap, retval)); 70741486Smckusick } 70841486Smckusick #endif 70941486Smckusick 71041486Smckusick /* 71141486Smckusick * Fake semaphore routines, just don't return an error. 71241486Smckusick * Should be adequate for starbase to run. 71341486Smckusick */ 71443452Shibler hpuxsemctl(p, uap, retval) 71543452Shibler struct proc *p; 71643452Shibler struct args { 71741486Smckusick int semid; 71841486Smckusick u_int semnum; 71941486Smckusick int cmd; 72041486Smckusick int arg; 72143452Shibler } *uap; 72243452Shibler int *retval; 72343452Shibler { 72441486Smckusick /* XXX: should do something here */ 72544421Skarels return (0); 72641486Smckusick } 72741486Smckusick 72843452Shibler hpuxsemget(p, uap, retval) 72943452Shibler struct proc *p; 73043452Shibler struct args { 73141486Smckusick key_t key; 73241486Smckusick int nsems; 73341486Smckusick int semflg; 73443452Shibler } *uap; 73543452Shibler int *retval; 73643452Shibler { 73741486Smckusick /* XXX: should do something here */ 73844421Skarels return (0); 73941486Smckusick } 74041486Smckusick 74143452Shibler hpuxsemop(p, uap, retval) 74243452Shibler struct proc *p; 74343452Shibler struct args { 74441486Smckusick int semid; 74541486Smckusick struct sembuf *sops; 74641486Smckusick u_int nsops; 74743452Shibler } *uap; 74843452Shibler int *retval; 74943452Shibler { 75041486Smckusick /* XXX: should do something here */ 75144421Skarels return (0); 75241486Smckusick } 75341486Smckusick 75441486Smckusick /* convert from BSD to HPUX errno */ 75541486Smckusick bsdtohpuxerrno(err) 75641486Smckusick int err; 75741486Smckusick { 75841486Smckusick if (err < 0 || err >= NERR) 75941486Smckusick return(BERR); 76041486Smckusick return((int)bsdtohpuxerrnomap[err]); 76141486Smckusick } 76241486Smckusick 76341486Smckusick hpuxstat1(fname, hsb, follow) 76441486Smckusick char *fname; 76541486Smckusick struct hpuxstat *hsb; 76641486Smckusick int follow; 76741486Smckusick { 76841486Smckusick register struct nameidata *ndp = &u.u_nd; 76941486Smckusick struct stat sb; 77041486Smckusick int error; 77141486Smckusick 77241486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 77341486Smckusick ndp->ni_segflg = UIO_USERSPACE; 77441486Smckusick ndp->ni_dirp = fname; 77541486Smckusick if (error = namei(ndp)) 77641486Smckusick return (error); 77741486Smckusick error = vn_stat(ndp->ni_vp, &sb); 77841486Smckusick vput(ndp->ni_vp); 77941486Smckusick if (error == 0) 78041486Smckusick error = bsdtohpuxstat(&sb, hsb); 78141486Smckusick return (error); 78241486Smckusick } 78341486Smckusick 78441486Smckusick #include "grf.h" 78541486Smckusick 78641486Smckusick bsdtohpuxstat(sb, hsb) 78741486Smckusick struct stat *sb; 78841486Smckusick struct hpuxstat *hsb; 78941486Smckusick { 79041486Smckusick struct hpuxstat ds; 79141486Smckusick 79241486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 79341486Smckusick ds.hst_dev = sb->st_dev; 79441486Smckusick ds.hst_ino = (u_long)sb->st_ino; 79541486Smckusick ds.hst_mode = sb->st_mode; 79641486Smckusick ds.hst_nlink = sb->st_nlink; 79741486Smckusick ds.hst_uid = (u_short)sb->st_uid; 79841486Smckusick ds.hst_gid = (u_short)sb->st_gid; 79941486Smckusick #if NGRF > 0 80041486Smckusick /* XXX: I don't want to talk about it... */ 80141486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 80241486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 80341486Smckusick else 80441486Smckusick #endif 80541486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 80641486Smckusick ds.hst_size = sb->st_size; 80741486Smckusick ds.hst_atime = sb->st_atime; 80841486Smckusick ds.hst_mtime = sb->st_mtime; 80941486Smckusick ds.hst_ctime = sb->st_ctime; 81041486Smckusick ds.hst_blksize = sb->st_blksize; 81141486Smckusick ds.hst_blocks = sb->st_blocks; 81241486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 81341486Smckusick } 81441486Smckusick 81541486Smckusick hpuxtobsdioctl(com) 81641486Smckusick int com; 81741486Smckusick { 81841486Smckusick switch (com) { 81941486Smckusick case HPUXTIOCSLTC: 82041486Smckusick com = TIOCSLTC; break; 82141486Smckusick case HPUXTIOCGLTC: 82241486Smckusick com = TIOCGLTC; break; 82341486Smckusick case HPUXTIOCSPGRP: 82441486Smckusick com = TIOCSPGRP; break; 82541486Smckusick case HPUXTIOCGPGRP: 82641486Smckusick com = TIOCGPGRP; break; 82741486Smckusick case HPUXTIOCLBIS: 82841486Smckusick com = TIOCLBIS; break; 82941486Smckusick case HPUXTIOCLBIC: 83041486Smckusick com = TIOCLBIC; break; 83141486Smckusick case HPUXTIOCLSET: 83241486Smckusick com = TIOCLSET; break; 83341486Smckusick case HPUXTIOCLGET: 83441486Smckusick com = TIOCLGET; break; 83541486Smckusick } 83641486Smckusick return(com); 83741486Smckusick } 83841486Smckusick 83941486Smckusick /* 84041486Smckusick * HPUX ioctl system call. The differences here are: 84141486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 84241486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 84341486Smckusick * the sgttyb struct is 2 bytes longer 84441486Smckusick */ 84543452Shibler hpuxioctl(p, uap, retval) 84643452Shibler struct proc *p; 84743452Shibler register struct args { 84841486Smckusick int fdes; 84941486Smckusick int cmd; 85041486Smckusick caddr_t cmarg; 85143452Shibler } *uap; 85243452Shibler int *retval; 85343452Shibler { 85443452Shibler register struct file *fp; 85543452Shibler register int com, error; 85641486Smckusick register u_int size; 85741486Smckusick caddr_t memp = 0; 85841486Smckusick #define STK_PARAMS 128 85941486Smckusick char stkbuf[STK_PARAMS]; 86041486Smckusick caddr_t data = stkbuf; 86141486Smckusick 86241486Smckusick com = uap->cmd; 86341486Smckusick 86441486Smckusick /* XXX */ 86543452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 86644421Skarels return (getsettty(uap->fdes, com, uap->cmarg)); 86741486Smckusick 86841486Smckusick if ((unsigned)uap->fdes >= NOFILE || 86943452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 87044421Skarels return (EBADF); 87143452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 87244421Skarels return (EBADF); 87341486Smckusick 87441486Smckusick /* 87541486Smckusick * Interpret high order word to find 87641486Smckusick * amount of data to be copied to/from the 87741486Smckusick * user's address space. 87841486Smckusick */ 87941486Smckusick size = IOCPARM_LEN(com); 88043452Shibler if (size > IOCPARM_MAX) 88144421Skarels return (ENOTTY); 88241486Smckusick if (size > sizeof (stkbuf)) { 88343452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 88441486Smckusick data = memp; 88541486Smckusick } 88641486Smckusick if (com&IOC_IN) { 88741486Smckusick if (size) { 88843452Shibler error = copyin(uap->cmarg, data, (u_int)size); 88943452Shibler if (error) { 89041486Smckusick if (memp) 89141486Smckusick free(memp, M_IOCTLOPS); 89244421Skarels return (error); 89341486Smckusick } 89441486Smckusick } else 89541486Smckusick *(caddr_t *)data = uap->cmarg; 89641486Smckusick } else if ((com&IOC_OUT) && size) 89741486Smckusick /* 89843452Shibler * Zero the buffer so the user always 89943452Shibler * gets back something deterministic. 90041486Smckusick */ 90141486Smckusick bzero(data, size); 90241486Smckusick else if (com&IOC_VOID) 90341486Smckusick *(caddr_t *)data = uap->cmarg; 90441486Smckusick 90541486Smckusick switch (com) { 90641486Smckusick 90741486Smckusick case HPUXTIOCCONS: 90841486Smckusick *(int *)data = 1; 90943452Shibler error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 91041486Smckusick break; 91141486Smckusick 91241486Smckusick /* BSD-style job control ioctls */ 91341486Smckusick case HPUXTIOCLBIS: 91441486Smckusick case HPUXTIOCLBIC: 91541486Smckusick case HPUXTIOCLSET: 91641486Smckusick *(int *)data &= HPUXLTOSTOP; 91741486Smckusick if (*(int *)data & HPUXLTOSTOP) 91841486Smckusick *(int *)data = LTOSTOP; 91941486Smckusick /* fall into */ 92041486Smckusick case HPUXTIOCLGET: 92141486Smckusick case HPUXTIOCSLTC: 92241486Smckusick case HPUXTIOCGLTC: 92341486Smckusick case HPUXTIOCSPGRP: 92441486Smckusick case HPUXTIOCGPGRP: 92543452Shibler error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 92643452Shibler if (error == 0 && com == HPUXTIOCLGET) { 92741486Smckusick *(int *)data &= LTOSTOP; 92841486Smckusick if (*(int *)data & LTOSTOP) 92941486Smckusick *(int *)data = HPUXLTOSTOP; 93041486Smckusick } 93141486Smckusick break; 93241486Smckusick 93341486Smckusick /* SYS 5 termio */ 93441486Smckusick case HPUXTCGETA: 93541486Smckusick case HPUXTCSETA: 93641486Smckusick case HPUXTCSETAW: 93741486Smckusick case HPUXTCSETAF: 93843452Shibler error = hpuxtermio(fp, com, data); 93941486Smckusick break; 94041486Smckusick 94141486Smckusick default: 94243452Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, data); 94341486Smckusick break; 94441486Smckusick } 94541486Smckusick /* 94641486Smckusick * Copy any data to user, size was 94741486Smckusick * already set and checked above. 94841486Smckusick */ 94943452Shibler if (error == 0 && (com&IOC_OUT) && size) 95043452Shibler error = copyout(data, uap->cmarg, (u_int)size); 95141486Smckusick if (memp) 95241486Smckusick free(memp, M_IOCTLOPS); 95344421Skarels return (error); 95441486Smckusick } 95541486Smckusick 95641486Smckusick /* 95741486Smckusick * Man page lies, behaviour here is based on observed behaviour. 95841486Smckusick */ 95943452Shibler hpuxgetcontext(p, uap, retval) 96043452Shibler struct proc *p; 96143452Shibler struct args { 96241486Smckusick char *buf; 96341486Smckusick int len; 96443452Shibler } *uap; 96543452Shibler int *retval; 96643452Shibler { 96741486Smckusick int error = 0; 96841486Smckusick register int len; 96941486Smckusick 97041486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 97141486Smckusick if (len) 97241486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 97343452Shibler if (error == 0) 97443452Shibler *retval = sizeof(hpuxcontext); 97544421Skarels return (error); 97641486Smckusick } 97741486Smckusick 97841486Smckusick /* 97941486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 98041486Smckusick * Note we do not check the real uid or "saved" uid. 98141486Smckusick */ 98243452Shibler hpuxgetpgrp2(cp, uap, retval) 98343452Shibler struct proc *cp; 98443452Shibler register struct args { 98543452Shibler int pid; 98643452Shibler } *uap; 98743452Shibler int *retval; 98841486Smckusick { 98941486Smckusick register struct proc *p; 99041486Smckusick 99141486Smckusick if (uap->pid == 0) 99243452Shibler uap->pid = cp->p_pid; 99341486Smckusick p = pfind(uap->pid); 99443452Shibler if (p == 0) 99544421Skarels return (ESRCH); 99643452Shibler if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) 99744421Skarels return (EPERM); 99843452Shibler *retval = p->p_pgid; 99944421Skarels return (0); 100041486Smckusick } 100141486Smckusick 100241486Smckusick /* 100341486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 100441486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 100541486Smckusick */ 100643452Shibler hpuxsetpgrp2(p, uap, retval) 100743452Shibler struct proc *p; 100843452Shibler struct args { 100941486Smckusick int pid; 101041486Smckusick int pgrp; 101143452Shibler } *uap; 101243452Shibler int *retval; 101343452Shibler { 101441486Smckusick /* empirically determined */ 101543452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 101644421Skarels return (EINVAL); 101744421Skarels return (setpgrp(p, uap, retval)); 101841486Smckusick } 101941486Smckusick 102041486Smckusick /* 1021*45753Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 1022*45753Smckusick */ 1023*45753Smckusick hpuxsetresuid(p, uap, retval) 1024*45753Smckusick struct proc *p; 1025*45753Smckusick struct args { 1026*45753Smckusick int ruid; 1027*45753Smckusick int euid; 1028*45753Smckusick int suid; 1029*45753Smckusick } *uap; 1030*45753Smckusick int *retval; 1031*45753Smckusick { 1032*45753Smckusick return (osetreuid(p, uap, retval)); 1033*45753Smckusick } 1034*45753Smckusick 1035*45753Smckusick hpuxsetresgid(p, uap, retval) 1036*45753Smckusick struct proc *p; 1037*45753Smckusick struct args { 1038*45753Smckusick int rgid; 1039*45753Smckusick int egid; 1040*45753Smckusick int sgid; 1041*45753Smckusick } *uap; 1042*45753Smckusick int *retval; 1043*45753Smckusick { 1044*45753Smckusick return (osetregid(p, uap, retval)); 1045*45753Smckusick } 1046*45753Smckusick 1047*45753Smckusick /* 1048*45753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 1049*45753Smckusick */ 1050*45753Smckusick hpuxlockf(p, uap, retval) 1051*45753Smckusick struct proc *p; 1052*45753Smckusick struct args { 1053*45753Smckusick int fd; 1054*45753Smckusick int func; 1055*45753Smckusick long size; 1056*45753Smckusick } *uap; 1057*45753Smckusick int *retval; 1058*45753Smckusick { 1059*45753Smckusick #ifdef DEBUG 1060*45753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 1061*45753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 1062*45753Smckusick #endif 1063*45753Smckusick return (0); 1064*45753Smckusick } 1065*45753Smckusick 1066*45753Smckusick hpuxgetaccess(p, uap, retval) 1067*45753Smckusick register struct proc *p; 1068*45753Smckusick register struct args { 1069*45753Smckusick char *path; 1070*45753Smckusick int uid; 1071*45753Smckusick int ngroups; 1072*45753Smckusick int *gidset; 1073*45753Smckusick void *label; 1074*45753Smckusick void *privs; 1075*45753Smckusick } *uap; 1076*45753Smckusick int *retval; 1077*45753Smckusick { 1078*45753Smckusick struct nameidata *ndp = &u.u_nd; 1079*45753Smckusick int lgroups[NGROUPS]; 1080*45753Smckusick int error = 0; 1081*45753Smckusick register struct ucred *cred; 1082*45753Smckusick register struct vnode *vp; 1083*45753Smckusick 1084*45753Smckusick /* 1085*45753Smckusick * Build an appropriate credential structure 1086*45753Smckusick */ 1087*45753Smckusick cred = crdup(ndp->ni_cred); 1088*45753Smckusick switch (uap->uid) { 1089*45753Smckusick case 65502: /* UID_EUID */ 1090*45753Smckusick break; 1091*45753Smckusick case 65503: /* UID_RUID */ 1092*45753Smckusick cred->cr_uid = p->p_ruid; 1093*45753Smckusick break; 1094*45753Smckusick case 65504: /* UID_SUID */ 1095*45753Smckusick error = EINVAL; 1096*45753Smckusick break; 1097*45753Smckusick default: 1098*45753Smckusick if (uap->uid > 65504) 1099*45753Smckusick error = EINVAL; 1100*45753Smckusick cred->cr_uid = uap->uid; 1101*45753Smckusick break; 1102*45753Smckusick } 1103*45753Smckusick switch (uap->ngroups) { 1104*45753Smckusick case -1: /* NGROUPS_EGID */ 1105*45753Smckusick cred->cr_ngroups = 1; 1106*45753Smckusick break; 1107*45753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 1108*45753Smckusick break; 1109*45753Smckusick case -2: /* NGROUPS_RGID */ 1110*45753Smckusick cred->cr_ngroups = 1; 1111*45753Smckusick cred->cr_gid = p->p_rgid; 1112*45753Smckusick break; 1113*45753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 1114*45753Smckusick cred->cr_gid = p->p_rgid; 1115*45753Smckusick break; 1116*45753Smckusick case -3: /* NGROUPS_SGID */ 1117*45753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 1118*45753Smckusick error = EINVAL; 1119*45753Smckusick break; 1120*45753Smckusick case -4: /* NGROUPS_SUPP */ 1121*45753Smckusick if (cred->cr_ngroups > 1) 1122*45753Smckusick cred->cr_gid = cred->cr_groups[1]; 1123*45753Smckusick else 1124*45753Smckusick error = EINVAL; 1125*45753Smckusick break; 1126*45753Smckusick default: 1127*45753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1128*45753Smckusick error = copyin((caddr_t)uap->gidset, 1129*45753Smckusick (caddr_t)&lgroups[0], 1130*45753Smckusick uap->ngroups * sizeof(lgroups[0])); 1131*45753Smckusick else 1132*45753Smckusick error = EINVAL; 1133*45753Smckusick if (error == 0) { 1134*45753Smckusick int gid; 1135*45753Smckusick 1136*45753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 1137*45753Smckusick cred->cr_groups[gid] = lgroups[gid]; 1138*45753Smckusick cred->cr_ngroups = uap->ngroups; 1139*45753Smckusick } 1140*45753Smckusick break; 1141*45753Smckusick } 1142*45753Smckusick /* 1143*45753Smckusick * Lookup file using caller's effective IDs. 1144*45753Smckusick */ 1145*45753Smckusick if (error == 0) { 1146*45753Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1147*45753Smckusick ndp->ni_segflg = UIO_USERSPACE; 1148*45753Smckusick ndp->ni_dirp = uap->path; 1149*45753Smckusick error = namei(ndp); 1150*45753Smckusick } 1151*45753Smckusick if (error) { 1152*45753Smckusick crfree(cred); 1153*45753Smckusick return (error); 1154*45753Smckusick } 1155*45753Smckusick /* 1156*45753Smckusick * Use the constructed credentials for access checks. 1157*45753Smckusick */ 1158*45753Smckusick vp = ndp->ni_vp; 1159*45753Smckusick *retval = 0; 1160*45753Smckusick if (VOP_ACCESS(vp, VREAD, cred) == 0) 1161*45753Smckusick *retval |= R_OK; 1162*45753Smckusick if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred) == 0) 1163*45753Smckusick *retval |= W_OK; 1164*45753Smckusick /* XXX we return X_OK for root on VREG even if not */ 1165*45753Smckusick if (VOP_ACCESS(vp, VEXEC, cred) == 0) 1166*45753Smckusick *retval |= X_OK; 1167*45753Smckusick vput(vp); 1168*45753Smckusick crfree(cred); 1169*45753Smckusick return (error); 1170*45753Smckusick } 1171*45753Smckusick 1172*45753Smckusick /* 117341486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 117441486Smckusick * No apologies offered, if you don't like it, rewrite it! 117541486Smckusick */ 117641486Smckusick 117741486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 117841486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 117941486Smckusick 118041486Smckusick /* simplified FP structure */ 118141486Smckusick struct bsdfp { 118241486Smckusick int save[54]; 118341486Smckusick int reg[24]; 118441486Smckusick int ctrl[3]; 118541486Smckusick }; 118641486Smckusick 118741486Smckusick hpuxtobsduoff(off) 118841486Smckusick int *off; 118941486Smckusick { 119041486Smckusick struct hpuxfp *hp; 119141486Smckusick struct bsdfp *bp; 119241486Smckusick register u_int raddr; 119341486Smckusick 119441486Smckusick /* u_ar0 field */ 119541486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 119641486Smckusick return(UOFF(u_ar0)); 119741486Smckusick 119841486Smckusick #ifdef FPCOPROC 119941486Smckusick /* 68881 registers from PCB */ 120041486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 120141486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 120241486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 120341486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 120441486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 120541486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 120641486Smckusick #endif 120741486Smckusick 120841486Smckusick /* 120941486Smckusick * Everything else we recognize comes from the kernel stack, 121041486Smckusick * so we convert off to an absolute address (if not already) 121141486Smckusick * for simplicity. 121241486Smckusick */ 121341486Smckusick if (off < (int *)ctob(UPAGES)) 121441486Smckusick off = (int *)((u_int)off + (u_int)&u); 121541486Smckusick 121641486Smckusick /* 121741486Smckusick * 68020 registers. 121841486Smckusick * We know that the HPUX registers are in the same order as ours. 121941486Smckusick * The only difference is that their PS is 2 bytes instead of a 122041486Smckusick * padded 4 like ours throwing the alignment off. 122141486Smckusick */ 122241486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 122341486Smckusick /* 122441486Smckusick * PS: return low word and high word of PC as HP-UX would 122541486Smckusick * (e.g. &u.u_ar0[16.5]). 122641486Smckusick */ 122741486Smckusick if (off == &u.u_ar0[PS]) 122841486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 122941486Smckusick /* 123041486Smckusick * PC: off will be &u.u_ar0[16.5] 123141486Smckusick */ 123241486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 123341486Smckusick raddr = (u_int) &u.u_ar0[PC]; 123441486Smckusick /* 123541486Smckusick * D0-D7, A0-A7: easy 123641486Smckusick */ 123741486Smckusick else 123841486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 123941486Smckusick return((int)(raddr - (u_int)&u)); 124041486Smckusick } 124141486Smckusick 124241486Smckusick /* everything else */ 124341486Smckusick return(-1); 124441486Smckusick } 124541486Smckusick 124641486Smckusick /* 124741486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 124841486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 124941486Smckusick * convert the entire user struct. 125041486Smckusick */ 125141486Smckusick hpuxdumpu(vp, cred) 125241486Smckusick struct vnode *vp; 125341486Smckusick struct ucred *cred; 125441486Smckusick { 125541486Smckusick int error; 125641486Smckusick struct hpuxuser *faku; 125741486Smckusick struct bsdfp *bp; 125841486Smckusick short *foop; 125941486Smckusick 126041486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 126141486Smckusick /* 126241486Smckusick * Make sure there is no mistake about this 126341486Smckusick * being a real user structure. 126441486Smckusick */ 126541486Smckusick bzero((caddr_t)faku, ctob(1)); 126641486Smckusick /* 126741486Smckusick * Fill in the process sizes. 126841486Smckusick */ 126941486Smckusick faku->hpuxu_tsize = u.u_tsize; 127041486Smckusick faku->hpuxu_dsize = u.u_dsize; 127141486Smckusick faku->hpuxu_ssize = u.u_ssize; 127241486Smckusick /* 127341486Smckusick * Fill in the exec header for CDB. 127441486Smckusick * This was saved back in exec(). As far as I can tell CDB 127541486Smckusick * only uses this information to verify that a particular 127641486Smckusick * core file goes with a particular binary. 127741486Smckusick */ 127841486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 127941486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 128041486Smckusick /* 128141486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 128241486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 128341486Smckusick * so we have to move it up. 128441486Smckusick */ 128541486Smckusick faku->hpuxu_ar0 = u.u_ar0; 128641486Smckusick foop = (short *) u.u_ar0; 128741486Smckusick foop[32] = foop[33]; 128841486Smckusick foop[33] = foop[34]; 128941486Smckusick foop[34] = foop[35]; 129041486Smckusick #ifdef FPCOPROC 129141486Smckusick /* 129241486Smckusick * Copy 68881 registers from our PCB format to HPUX format 129341486Smckusick */ 129441486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 129541486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 129641486Smckusick sizeof(bp->save)); 129741486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 129841486Smckusick sizeof(bp->ctrl)); 129941486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 130041486Smckusick sizeof(bp->reg)); 130141486Smckusick #endif 130241486Smckusick /* 130341486Smckusick * Slay the dragon 130441486Smckusick */ 130541486Smckusick faku->hpuxu_dragon = -1; 130641486Smckusick /* 130741486Smckusick * Dump this artfully constructed page in place of the 130841486Smckusick * user struct page. 130941486Smckusick */ 131041486Smckusick error = vn_rdwr(UIO_WRITE, vp, 131141486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 131241486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 131341486Smckusick /* 131441486Smckusick * Dump the remaining UPAGES-1 pages normally 131541486Smckusick */ 131641486Smckusick if (!error) 131741486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 131841486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 131941486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 132041486Smckusick free((caddr_t)faku, M_TEMP); 132141486Smckusick return(error); 132241486Smckusick } 132341486Smckusick 132441486Smckusick /* 132541486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 132641486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 132741486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 132841486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 132941486Smckusick */ 133041486Smckusick /* #ifdef COMPAT */ 133141486Smckusick 1332*45753Smckusick #define HPUX_HZ 50 1333*45753Smckusick 133442088Smckusick #include "../sys/times.h" 133541486Smckusick 133641486Smckusick /* from old timeb.h */ 133741486Smckusick struct hpuxtimeb { 133841486Smckusick time_t time; 133941486Smckusick u_short millitm; 134041486Smckusick short timezone; 134141486Smckusick short dstflag; 134241486Smckusick }; 134341486Smckusick 134441486Smckusick /* ye ole stat structure */ 134541486Smckusick struct ohpuxstat { 134641486Smckusick dev_t ohst_dev; 134741486Smckusick u_short ohst_ino; 134841486Smckusick u_short ohst_mode; 134941486Smckusick short ohst_nlink; 135041486Smckusick short ohst_uid; 135141486Smckusick short ohst_gid; 135241486Smckusick dev_t ohst_rdev; 135341486Smckusick int ohst_size; 135441486Smckusick int ohst_atime; 135541486Smckusick int ohst_mtime; 135641486Smckusick int ohst_ctime; 135741486Smckusick }; 135841486Smckusick 135941486Smckusick /* 136041486Smckusick * SYS V style setpgrp() 136141486Smckusick */ 136243452Shibler ohpuxsetpgrp(p, uap, retval) 136343452Shibler register struct proc *p; 136443452Shibler int *uap, *retval; 136541486Smckusick { 136641486Smckusick if (p->p_pid != p->p_pgid) 136741486Smckusick pgmv(p, p->p_pid, 0); 136843452Shibler *retval = p->p_pgid; 1369*45753Smckusick return (0); 137041486Smckusick } 137141486Smckusick 137243452Shibler ohpuxtime(p, uap, retval) 137343452Shibler struct proc *p; 137443452Shibler register struct args { 137543452Shibler long *tp; 137643452Shibler } *uap; 137743713Smckusick time_t *retval; 137841486Smckusick { 1379*45753Smckusick int error = 0; 138041486Smckusick 138141486Smckusick if (uap->tp) 138243452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 138343452Shibler sizeof (long)); 1384*45753Smckusick *retval = time.tv_sec; 138544421Skarels return (error); 138641486Smckusick } 138741486Smckusick 138843452Shibler ohpuxstime(p, uap, retval) 138943452Shibler struct proc *p; 139043452Shibler register struct args { 139143452Shibler int time; 139243452Shibler } *uap; 139343452Shibler int *retval; 139441486Smckusick { 139541486Smckusick struct timeval tv; 139643452Shibler int s, error; 139741486Smckusick 139841486Smckusick tv.tv_sec = uap->time; 139941486Smckusick tv.tv_usec = 0; 140043452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 140144421Skarels return (error); 140241486Smckusick 140341486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 140441486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 140541486Smckusick s = splhigh(); time = tv; splx(s); 140641486Smckusick resettodr(); 140744421Skarels return (0); 140841486Smckusick } 140941486Smckusick 141043452Shibler ohpuxftime(p, uap, retval) 141143452Shibler struct proc *p; 141243452Shibler register struct args { 141341486Smckusick struct hpuxtimeb *tp; 141441486Smckusick } *uap; 141543452Shibler int *retval; 141643452Shibler { 141741486Smckusick struct hpuxtimeb tb; 141841486Smckusick int s; 141941486Smckusick 142041486Smckusick s = splhigh(); 142141486Smckusick tb.time = time.tv_sec; 142241486Smckusick tb.millitm = time.tv_usec / 1000; 142341486Smckusick splx(s); 142441486Smckusick tb.timezone = tz.tz_minuteswest; 142541486Smckusick tb.dstflag = tz.tz_dsttime; 142644421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 142741486Smckusick } 142841486Smckusick 142943452Shibler ohpuxalarm(p, uap, retval) 143043452Shibler register struct proc *p; 143143452Shibler register struct args { 143243452Shibler int deltat; 143343452Shibler } *uap; 143443452Shibler int *retval; 143541486Smckusick { 143641486Smckusick int s = splhigh(); 143741486Smckusick 143841486Smckusick untimeout(realitexpire, (caddr_t)p); 143941486Smckusick timerclear(&p->p_realtimer.it_interval); 144043452Shibler *retval = 0; 144141486Smckusick if (timerisset(&p->p_realtimer.it_value) && 144241486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 144343452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 144441486Smckusick if (uap->deltat == 0) { 144541486Smckusick timerclear(&p->p_realtimer.it_value); 144641486Smckusick splx(s); 144744421Skarels return (0); 144841486Smckusick } 144941486Smckusick p->p_realtimer.it_value = time; 145041486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 145141486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 145241486Smckusick splx(s); 145344421Skarels return (0); 145441486Smckusick } 145541486Smckusick 145643452Shibler ohpuxnice(p, uap, retval) 145743452Shibler register struct proc *p; 145843452Shibler register struct args { 145943452Shibler int niceness; 146043452Shibler } *uap; 146143452Shibler int *retval; 146241486Smckusick { 146343452Shibler int error; 146441486Smckusick 146543452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 146643452Shibler if (error == 0) 146743452Shibler *retval = p->p_nice - NZERO; 146844421Skarels return (error); 146941486Smckusick } 147041486Smckusick 147143452Shibler ohpuxtimes(p, uap, retval) 147243452Shibler struct proc *p; 147343452Shibler register struct args { 147443452Shibler struct tms *tmsb; 147543452Shibler } *uap; 147643713Smckusick time_t *retval; 147741486Smckusick { 147841486Smckusick struct tms atms; 147943452Shibler int error; 148041486Smckusick 1481*45753Smckusick atms.tms_utime = hpuxscale(&u.u_ru.ru_utime); 1482*45753Smckusick atms.tms_stime = hpuxscale(&u.u_ru.ru_stime); 1483*45753Smckusick atms.tms_cutime = hpuxscale(&u.u_cru.ru_utime); 1484*45753Smckusick atms.tms_cstime = hpuxscale(&u.u_cru.ru_stime); 148543452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 148643452Shibler if (error == 0) 1487*45753Smckusick *retval = hpuxscale(&time) - hpuxscale(&boottime); 148844421Skarels return (error); 148941486Smckusick } 149041486Smckusick 1491*45753Smckusick /* 1492*45753Smckusick * Doesn't exactly do what the documentation says. 1493*45753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 1494*45753Smckusick * is what HP-UX returns. 1495*45753Smckusick */ 1496*45753Smckusick hpuxscale(tvp) 149741486Smckusick register struct timeval *tvp; 149841486Smckusick { 1499*45753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 150041486Smckusick } 150141486Smckusick 150241486Smckusick /* 150341486Smckusick * Set IUPD and IACC times on file. 150441486Smckusick * Can't set ICHG. 150541486Smckusick */ 150643452Shibler ohpuxutime(p, uap, retval) 150743452Shibler struct proc *p; 150841486Smckusick register struct a { 150941486Smckusick char *fname; 151041486Smckusick time_t *tptr; 151143452Shibler } *uap; 151243452Shibler int *retval; 151343452Shibler { 151441486Smckusick struct vattr vattr; 151541486Smckusick time_t tv[2]; 151641486Smckusick register struct vnode *vp; 151741486Smckusick register struct nameidata *ndp = &u.u_nd; 151843452Shibler int error; 151941486Smckusick 152041486Smckusick if (uap->tptr) { 152143452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 152243452Shibler if (error) 152344421Skarels return (error); 152441486Smckusick } else 152541486Smckusick tv[0] = tv[1] = time.tv_sec; 152641486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 152741486Smckusick ndp->ni_segflg = UIO_USERSPACE; 152841486Smckusick ndp->ni_dirp = uap->fname; 152941486Smckusick vattr_null(&vattr); 153041486Smckusick vattr.va_atime.tv_sec = tv[0]; 153141486Smckusick vattr.va_atime.tv_usec = 0; 153241486Smckusick vattr.va_mtime.tv_sec = tv[1]; 153341486Smckusick vattr.va_mtime.tv_usec = 0; 153443452Shibler if (error = namei(ndp)) 153544421Skarels return (error); 153641486Smckusick vp = ndp->ni_vp; 153742154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 153843452Shibler error = EROFS; 153941486Smckusick else 154043452Shibler error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 154141486Smckusick vput(vp); 154244421Skarels return (error); 154341486Smckusick } 154441486Smckusick 154543452Shibler ohpuxpause(p, uap, retval) 154643452Shibler struct proc *p; 154743452Shibler int *uap, *retval; 154841486Smckusick { 154942155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 155042155Skarels /* always return EINTR rather than ERESTART... */ 155144421Skarels return (EINTR); 155241486Smckusick } 155341486Smckusick 155441486Smckusick /* 155541486Smckusick * The old fstat system call. 155641486Smckusick */ 155743452Shibler ohpuxfstat(p, uap, retval) 155843452Shibler struct proc *p; 155943452Shibler register struct args { 156041486Smckusick int fd; 156141486Smckusick struct ohpuxstat *sb; 156243452Shibler } *uap; 156343452Shibler int *retval; 156443452Shibler { 156541486Smckusick struct file *fp; 156641486Smckusick 156743452Shibler if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) 156844421Skarels return (EBADF); 156943452Shibler if (fp->f_type != DTYPE_VNODE) 157044421Skarels return (EINVAL); 157144421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 157241486Smckusick } 157341486Smckusick 157441486Smckusick /* 157541486Smckusick * Old stat system call. This version follows links. 157641486Smckusick */ 157743452Shibler ohpuxstat(p, uap, retval) 157843452Shibler struct proc *p; 157943452Shibler register struct args { 158041486Smckusick char *fname; 158141486Smckusick struct ohpuxstat *sb; 158243452Shibler } *uap; 158343452Shibler int *retval; 158443452Shibler { 158541486Smckusick register struct nameidata *ndp = &u.u_nd; 158643452Shibler int error; 158741486Smckusick 158841486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 158941486Smckusick ndp->ni_segflg = UIO_USERSPACE; 159041486Smckusick ndp->ni_dirp = uap->fname; 159143452Shibler if (error = namei(ndp)) 159244421Skarels return (error); 159343452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 159441486Smckusick vput(ndp->ni_vp); 159544421Skarels return (error); 159641486Smckusick } 159741486Smckusick 159841486Smckusick int 159941486Smckusick ohpuxstat1(vp, ub) 160041486Smckusick register struct vnode *vp; 160141486Smckusick struct ohpuxstat *ub; 160241486Smckusick { 160341486Smckusick struct ohpuxstat ds; 160441486Smckusick struct vattr vattr; 160541486Smckusick register int error; 160641486Smckusick 160741486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 160841486Smckusick if (error) 160941486Smckusick return(error); 161041486Smckusick /* 161141486Smckusick * Copy from inode table 161241486Smckusick */ 161341486Smckusick ds.ohst_dev = vattr.va_fsid; 161441486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 161541486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 161641486Smckusick ds.ohst_nlink = vattr.va_nlink; 161741486Smckusick ds.ohst_uid = (short)vattr.va_uid; 161841486Smckusick ds.ohst_gid = (short)vattr.va_gid; 161941486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 162041486Smckusick ds.ohst_size = (int)vattr.va_size; 162141486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 162241486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 162341486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 162441486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 162541486Smckusick } 162641486Smckusick /* #endif */ 162741486Smckusick 162841486Smckusick #endif 1629