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 * 1241486Smckusick * from: Utah $Hdr: hpux_compat.c 1.33 89/08/23$ 1341486Smckusick * 14*44421Skarels * @(#)hpux_compat.c 7.9 (Berkeley) 06/28/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Various HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2341486Smckusick #include "param.h" 2441486Smckusick #include "systm.h" 25*44421Skarels #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 /* "tick" value for HZ==50 */ 5341486Smckusick int hpuxtick = 1000000 / 50; 5441486Smckusick 5541486Smckusick /* SYS5 style UTSNAME info */ 5641486Smckusick struct hpuxutsname protoutsname = { 5741486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5841486Smckusick }; 5941486Smckusick 6041486Smckusick /* 6.0 and later style context */ 6141486Smckusick #ifdef FPCOPROC 6241486Smckusick char hpuxcontext[] = 6341486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6441486Smckusick #else 6541486Smckusick char hpuxcontext[] = 6641486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 6741486Smckusick #endif 6841486Smckusick 6941486Smckusick /* YP domainname */ 7041486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7141486Smckusick int domainnamelen = 7; 7241486Smckusick 7341486Smckusick #define NERR 79 7441486Smckusick #define BERR 1000 7541486Smckusick 7641486Smckusick /* indexed by BSD errno */ 7741486Smckusick short bsdtohpuxerrnomap[NERR] = { 7841486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7941486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8041486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8141486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8241486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8341486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8441486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8541486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 8641486Smckusick }; 8741486Smckusick 8843452Shibler notimp(p, uap, retval, code, nargs) 8943452Shibler struct proc *p; 9043452Shibler int *uap, *retval; 9143452Shibler int code, nargs; 9241486Smckusick { 9343452Shibler int error = 0; 9441486Smckusick #ifdef DEBUG 9543452Shibler register int *argp = uap; 9641486Smckusick extern char *hpuxsyscallnames[]; 9741486Smckusick 9841486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9941486Smckusick if (nargs) 10041486Smckusick while (nargs--) 10141486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10241486Smckusick else 10341486Smckusick printf(")"); 10441486Smckusick printf("\n"); 10541486Smckusick switch (unimpresponse) { 10641486Smckusick case 0: 10743452Shibler error = nosys(p, uap, retval); 10841486Smckusick break; 10941486Smckusick case 1: 11043452Shibler error = EINVAL; 11141486Smckusick break; 11241486Smckusick } 11341486Smckusick #else 11443452Shibler error = nosys(p, uap, retval); 11541486Smckusick #endif 11643452Shibler uprintf("HP-UX system call %d not implemented\n", code); 117*44421Skarels return (error); 11841486Smckusick } 11941486Smckusick 12041486Smckusick /* 12141486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 12241486Smckusick * (status pointer, options, rusage) into the kernel rather than 12342352Smckusick * handling it in the C library stub. We also need to map any 12442352Smckusick * termination signal from BSD to HPUX. 12541486Smckusick */ 12643452Shibler hpuxwait3(p, uap, retval) 12743452Shibler struct proc *p; 12843452Shibler struct args { 12941486Smckusick int *status; 13041486Smckusick int options; 13141486Smckusick int rusage; 13243452Shibler } *uap; 13343452Shibler int *retval; 13443452Shibler { 13541486Smckusick /* rusage pointer must be zero */ 13643452Shibler if (uap->rusage) 137*44421Skarels return (EINVAL); 13841486Smckusick u.u_ar0[PS] = PSL_ALLCC; 13941486Smckusick u.u_ar0[R0] = uap->options; 14041486Smckusick u.u_ar0[R1] = uap->rusage; 141*44421Skarels return (hpuxwait(p, uap, retval)); 14241486Smckusick } 14341486Smckusick 14443452Shibler hpuxwait(p, uap, retval) 14543452Shibler struct proc *p; 14643452Shibler struct args { 14743452Shibler int *status; 14843452Shibler } *uap; 14943452Shibler int *retval; 15041486Smckusick { 15143452Shibler int sig, *statp, error; 15241486Smckusick 15341486Smckusick statp = uap->status; /* owait clobbers first arg */ 15443452Shibler error = owait(p, uap, retval); 15541486Smckusick /* 15641486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 15741486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 15841486Smckusick */ 15943452Shibler if (error == ERESTART) 16043452Shibler error = EINTR; 16143452Shibler if (error) 162*44421Skarels return (error); 16343452Shibler sig = retval[1] & 0xFF; 16441486Smckusick if (sig == WSTOPPED) { 16543452Shibler sig = (retval[1] >> 8) & 0xFF; 16643452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 16741486Smckusick } else if (sig) 16843452Shibler retval[1] = (retval[1] & 0xFF00) | 16941486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 17041486Smckusick if (statp) 17143452Shibler if (suword((caddr_t)statp, retval[1])) 17243452Shibler error = EFAULT; 173*44421Skarels return (error); 17441486Smckusick } 17541486Smckusick 17643452Shibler hpuxwaitpid(p, uap, retval) 17743452Shibler struct proc *p; 17843452Shibler struct args { 17942352Smckusick int pid; 18042352Smckusick int *status; 18142352Smckusick int options; 18242352Smckusick struct rusage *rusage; /* wait4 arg */ 18343452Shibler } *uap; 18443452Shibler int *retval; 18543452Shibler { 18643452Shibler int sig, *statp, error; 18742352Smckusick 18842352Smckusick uap->rusage = 0; 18943452Shibler error = wait4(p, uap, retval); 19042352Smckusick /* 19142352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 19242352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 19342352Smckusick */ 19443452Shibler if (error == ERESTART) 19543452Shibler error = EINTR; 19643452Shibler if (error) 197*44421Skarels return (error); 19843452Shibler sig = retval[1] & 0xFF; 19942352Smckusick if (sig == WSTOPPED) { 20043452Shibler sig = (retval[1] >> 8) & 0xFF; 20143452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 20242352Smckusick } else if (sig) 20343452Shibler retval[1] = (retval[1] & 0xFF00) | 20442352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 20542352Smckusick if (statp) 20643452Shibler if (suword((caddr_t)statp, retval[1])) 20743452Shibler error = EFAULT; 208*44421Skarels return (error); 20942352Smckusick } 21042352Smckusick 21141486Smckusick /* 21241486Smckusick * Must remap some bits in the mode mask. 21341486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 21441486Smckusick * O_SYNCIO (0100000) is removed entirely. 21541486Smckusick */ 21643067Skarels hpuxopen(p, uap, retval) 21743067Skarels struct proc *p; 21843452Shibler register struct args { 21941486Smckusick char *fname; 22041486Smckusick int mode; 22141486Smckusick int crtmode; 22243067Skarels } *uap; 22343067Skarels int *retval; 22443067Skarels { 22541486Smckusick int mode; 22641486Smckusick 22741486Smckusick mode = uap->mode; 22841486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 22941486Smckusick if (mode & HPUXFCREAT) { 23041486Smckusick /* 23141486Smckusick * simulate the pre-NFS behavior that opening a 23241486Smckusick * file for READ+CREATE ignores the CREATE (unless 23341486Smckusick * EXCL is set in which case we will return the 23441486Smckusick * proper error). 23541486Smckusick */ 23641486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 23741486Smckusick uap->mode |= FCREAT; 23841486Smckusick } 23941486Smckusick if (mode & HPUXFTRUNC) 24041486Smckusick uap->mode |= FTRUNC; 24141486Smckusick if (mode & HPUXFEXCL) 24241486Smckusick uap->mode |= FEXCL; 243*44421Skarels return (open(p, uap, retval)); 24441486Smckusick } 24541486Smckusick 24643452Shibler hpuxfcntl(p, uap, retval) 24743452Shibler struct proc *p; 24843452Shibler register struct args { 24941486Smckusick int fdes; 25041486Smckusick int cmd; 25141486Smckusick int arg; 25243452Shibler } *uap; 25343452Shibler int *retval; 25443452Shibler { 25543452Shibler int mode, error; 25641486Smckusick 25741486Smckusick switch (uap->cmd) { 25841486Smckusick case F_SETFL: 25941486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 26041486Smckusick break; 26141486Smckusick case F_GETFL: 26241486Smckusick case F_DUPFD: 26341486Smckusick case F_GETFD: 26441486Smckusick case F_SETFD: 26541486Smckusick break; 26641486Smckusick default: 267*44421Skarels return (EINVAL); 26841486Smckusick } 26943452Shibler error = fcntl(p, uap, retval); 27043452Shibler if (error == 0 && uap->arg == F_GETFL) { 27143452Shibler mode = *retval; 27243452Shibler *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 27341486Smckusick if (mode & FCREAT) 27443452Shibler *retval |= HPUXFCREAT; 27541486Smckusick if (mode & FTRUNC) 27643452Shibler *retval |= HPUXFTRUNC; 27741486Smckusick if (mode & FEXCL) 27843452Shibler *retval |= HPUXFEXCL; 27941486Smckusick } 280*44421Skarels return (error); 28141486Smckusick } 28241486Smckusick 28341486Smckusick /* 28441486Smckusick * Read and write should return a 0 count when an operation 28541486Smckusick * on a VNODE would block, not an error. Sockets appear to 28641486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 28741486Smckusick * not entirely correct, since the behavior is only defined 28841486Smckusick * for pipes and tty type devices. 28941486Smckusick */ 29043452Shibler hpuxread(p, uap, retval) 29143452Shibler struct proc *p; 29243452Shibler struct args { 29343452Shibler int fd; 29443452Shibler } *uap; 29543452Shibler int *retval; 29641486Smckusick { 29743452Shibler int error; 29841486Smckusick 29943452Shibler error = read(p, uap, retval); 30043452Shibler if (error == EWOULDBLOCK && 30141486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 30243452Shibler error = 0; 30343452Shibler *retval = 0; 30441486Smckusick } 305*44421Skarels return (error); 30641486Smckusick } 30741486Smckusick 30843452Shibler hpuxwrite(p, uap, retval) 30943452Shibler struct proc *p; 31043452Shibler struct args { 31143452Shibler int fd; 31243452Shibler } *uap; 31343452Shibler int *retval; 31441486Smckusick { 31543452Shibler int error; 31641486Smckusick 31743452Shibler error = write(p, uap, retval); 31843452Shibler if (error == EWOULDBLOCK && 31941486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 32043452Shibler error = 0; 32143452Shibler *retval = 0; 32241486Smckusick } 323*44421Skarels return (error); 32441486Smckusick } 32541486Smckusick 32643452Shibler hpuxreadv(p, uap, retval) 32743452Shibler struct proc *p; 32843452Shibler struct args { 32943452Shibler int fd; 33043452Shibler } *uap; 33143452Shibler int *retval; 33241486Smckusick { 33343452Shibler int error; 33441486Smckusick 33543452Shibler error = readv(p, uap, retval); 33643452Shibler if (error == EWOULDBLOCK && 33741486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 33843452Shibler error = 0; 33943452Shibler *retval = 0; 34041486Smckusick } 341*44421Skarels return (error); 34241486Smckusick } 34341486Smckusick 34443452Shibler hpuxwritev(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 = writev(p, uap, retval); 35443452Shibler if (error == EWOULDBLOCK && 35541486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 35643452Shibler error = 0; 35743452Shibler *retval = 0; 35841486Smckusick } 359*44421Skarels return (error); 36041486Smckusick } 36141486Smckusick 36241486Smckusick /* 36341486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 36441486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 36541486Smckusick */ 36643452Shibler hpuxdup(p, uap, retval) 36743452Shibler struct proc *p; 36843452Shibler register struct args { 36943452Shibler int i; 37043452Shibler } *uap; 37143452Shibler int *retval; 37241486Smckusick { 37341486Smckusick struct file *fp; 37443452Shibler int fd, error; 37541486Smckusick 37643452Shibler if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 377*44421Skarels return (EBADF); 37843452Shibler if (error = ufalloc(0, &fd)) 379*44421Skarels return (error); 38043452Shibler *retval = fd; 38143452Shibler u.u_ofile[fd] = fp; 38243452Shibler u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 38343067Skarels fp->f_count++; 38443452Shibler if (fd > u.u_lastfile) 38543452Shibler u.u_lastfile = fd; 386*44421Skarels return (0); 38741486Smckusick } 38841486Smckusick 38943452Shibler hpuxuname(p, uap, retval) 39043452Shibler struct proc *p; 39143452Shibler register struct args { 39241486Smckusick struct hpuxutsname *uts; 39341486Smckusick int dev; 39441486Smckusick int request; 39543452Shibler } *uap; 39643452Shibler int *retval; 39743452Shibler { 39841486Smckusick register int i; 39943452Shibler int error; 40041486Smckusick 40141486Smckusick switch (uap->request) { 40241486Smckusick /* uname */ 40341486Smckusick case 0: 40441486Smckusick /* fill in machine type */ 40541486Smckusick switch (machineid) { 40641486Smckusick case HP_320: 40741486Smckusick protoutsname.machine[6] = '2'; 40841486Smckusick break; 40941486Smckusick /* includes 318 and 319 */ 41041486Smckusick case HP_330: 41141486Smckusick protoutsname.machine[6] = '3'; 41241486Smckusick break; 41341486Smckusick case HP_340: 41441486Smckusick protoutsname.machine[6] = '4'; 41541486Smckusick break; 41641486Smckusick case HP_350: 41741486Smckusick protoutsname.machine[6] = '5'; 41841486Smckusick break; 41941486Smckusick case HP_360: 42041486Smckusick protoutsname.machine[6] = '6'; 42141486Smckusick break; 42241486Smckusick case HP_370: 42341486Smckusick protoutsname.machine[6] = '7'; 42441486Smckusick break; 42543452Shibler /* includes 345 */ 42643452Shibler case HP_375: 42743452Shibler protoutsname.machine[6] = '7'; 42843452Shibler protoutsname.machine[7] = '5'; 42943452Shibler break; 43041486Smckusick } 43141486Smckusick /* copy hostname (sans domain) to nodename */ 43241486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 43341486Smckusick protoutsname.nodename[i] = hostname[i]; 43443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 43543452Shibler sizeof(struct hpuxutsname)); 43641486Smckusick break; 43741486Smckusick /* ustat - who cares? */ 43841486Smckusick case 2: 43941486Smckusick default: 44043452Shibler error = EINVAL; 44141486Smckusick break; 44241486Smckusick } 443*44421Skarels return (error); 44441486Smckusick } 44541486Smckusick 44643452Shibler hpuxstat(p, uap, retval) 44743452Shibler struct proc *p; 44843452Shibler struct args { 44941486Smckusick char *fname; 45041486Smckusick struct hpuxstat *hsb; 45143452Shibler } *uap; 45243452Shibler int *retval; 45343452Shibler { 454*44421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 45541486Smckusick } 45641486Smckusick 45743452Shibler hpuxlstat(p, uap, retval) 45843452Shibler struct proc *p; 45943452Shibler struct args { 46043452Shibler char *fname; 46143452Shibler struct hpuxstat *hsb; 46243452Shibler } *uap; 46343452Shibler int *retval; 46441486Smckusick { 465*44421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 46641486Smckusick } 46741486Smckusick 46843452Shibler hpuxfstat(p, uap, retval) 46943452Shibler struct proc *p; 47043452Shibler register struct args { 47143452Shibler int fdes; 47243452Shibler struct hpuxstat *hsb; 47343452Shibler } *uap; 47443452Shibler int *retval; 47541486Smckusick { 47641486Smckusick register struct file *fp; 47741486Smckusick struct stat sb; 47843452Shibler int error; 47941486Smckusick 48041486Smckusick if ((unsigned)uap->fdes >= NOFILE || 48143452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 482*44421Skarels return (EBADF); 48343452Shibler 48441486Smckusick switch (fp->f_type) { 48541486Smckusick 48641486Smckusick case DTYPE_VNODE: 48743452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 48841486Smckusick break; 48941486Smckusick 49041486Smckusick case DTYPE_SOCKET: 49143452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 49241486Smckusick break; 49341486Smckusick 49441486Smckusick default: 49541486Smckusick panic("fstat"); 49641486Smckusick /*NOTREACHED*/ 49741486Smckusick } 49841486Smckusick /* is this right for sockets?? */ 49943452Shibler if (error == 0) 50043452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 501*44421Skarels return (error); 50241486Smckusick } 50341486Smckusick 50443452Shibler hpuxulimit(p, uap, retval) 50543452Shibler struct proc *p; 50643452Shibler register struct args { 50741486Smckusick int cmd; 50841486Smckusick long newlimit; 50943452Shibler } *uap; 51043713Smckusick off_t *retval; 51143452Shibler { 51241486Smckusick struct rlimit *limp; 51343452Shibler int error = 0; 51441486Smckusick 51541486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 51641486Smckusick switch (uap->cmd) { 51741486Smckusick case 2: 51841486Smckusick uap->newlimit *= 512; 51941486Smckusick if (uap->newlimit > limp->rlim_max && 52043452Shibler (error = suser(u.u_cred, &u.u_acflag))) 52141486Smckusick break; 52241486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 52341486Smckusick /* else fall into... */ 52441486Smckusick 52541486Smckusick case 1: 52643713Smckusick *retval = limp->rlim_max / 512; /* XXX */ 52741486Smckusick break; 52841486Smckusick 52941486Smckusick case 3: 53041486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 53143713Smckusick *retval = ctob(u.u_tsize) + limp->rlim_max; /* XXX */ 53241486Smckusick break; 53341486Smckusick 53441486Smckusick default: 53543452Shibler error = EINVAL; 53641486Smckusick break; 53741486Smckusick } 538*44421Skarels return (error); 53941486Smckusick } 54041486Smckusick 54141486Smckusick /* 54241486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 54341486Smckusick * values -16 (high) thru -1 (low). 54441486Smckusick */ 54543452Shibler hpuxrtprio(cp, uap, retval) 54643452Shibler struct proc *cp; 54743452Shibler register struct args { 54841486Smckusick int pid; 54941486Smckusick int prio; 55043452Shibler } *uap; 55143452Shibler int *retval; 55243452Shibler { 55341486Smckusick struct proc *p; 55443452Shibler int nice, error; 55541486Smckusick 55641486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 55743452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 558*44421Skarels return (EINVAL); 55941486Smckusick if (uap->pid == 0) 56043452Shibler p = cp; 56143452Shibler else if ((p = pfind(uap->pid)) == 0) 562*44421Skarels return (ESRCH); 56341486Smckusick nice = p->p_nice; 56441486Smckusick if (nice < NZERO) 56543452Shibler *retval = (nice + 16) << 3; 56641486Smckusick else 56743452Shibler *retval = RTPRIO_RTOFF; 56841486Smckusick switch (uap->prio) { 56941486Smckusick 57041486Smckusick case RTPRIO_NOCHG: 571*44421Skarels return (0); 57241486Smckusick 57341486Smckusick case RTPRIO_RTOFF: 57441486Smckusick if (nice >= NZERO) 575*44421Skarels return (0); 57641486Smckusick nice = NZERO; 57741486Smckusick break; 57841486Smckusick 57941486Smckusick default: 58041486Smckusick nice = (uap->prio >> 3) - 16; 58141486Smckusick break; 58241486Smckusick } 58343452Shibler error = donice(cp, p, nice); 58443452Shibler if (error == EACCES) 58543452Shibler error = EPERM; 586*44421Skarels return (error); 58741486Smckusick } 58841486Smckusick 58943452Shibler hpuxadvise(p, uap, retval) 59043452Shibler struct proc *p; 59143452Shibler struct args { 59243452Shibler int arg; 59343452Shibler } *uap; 59443452Shibler int *retval; 59541486Smckusick { 59643452Shibler int error = 0; 59741486Smckusick 59841486Smckusick switch (uap->arg) { 59941486Smckusick case 0: 60041486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 60141486Smckusick break; 60241486Smckusick case 1: 60341486Smckusick ICIA(); 60441486Smckusick break; 60541486Smckusick case 2: 60641486Smckusick DCIA(); 60741486Smckusick break; 60841486Smckusick default: 60943452Shibler error = EINVAL; 61041486Smckusick break; 61141486Smckusick } 612*44421Skarels return (error); 61341486Smckusick } 61441486Smckusick 61543452Shibler hpuxptrace(p, uap, retval) 61643452Shibler struct proc *p; 61743452Shibler struct args { 61841486Smckusick int req; 61941486Smckusick int pid; 62041486Smckusick int *addr; 62141486Smckusick int data; 62243452Shibler } *uap; 62343452Shibler int *retval; 62443452Shibler { 62543452Shibler int error; 62641486Smckusick 62741486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 62841486Smckusick if (uap->data) { 62941486Smckusick uap->data = hpuxtobsdsig(uap->data); 63041486Smckusick if (uap->data == 0) 63141486Smckusick uap->data = NSIG; 63241486Smckusick } 63341486Smckusick } 63443452Shibler error = ptrace(p, uap, retval); 635*44421Skarels return (error); 63641486Smckusick } 63741486Smckusick 63843452Shibler hpuxgetdomainname(p, uap, retval) 63943452Shibler struct proc *p; 64043452Shibler register struct args { 64141486Smckusick char *domainname; 64241486Smckusick u_int len; 64343452Shibler } *uap; 64443452Shibler int *retval; 64543452Shibler { 64641486Smckusick if (uap->len > domainnamelen + 1) 64741486Smckusick uap->len = domainnamelen + 1; 648*44421Skarels return (copyout(domainname, uap->domainname, uap->len)); 64941486Smckusick } 65041486Smckusick 65143452Shibler hpuxsetdomainname(p, uap, retval) 65243452Shibler struct proc *p; 65343452Shibler register struct args { 65441486Smckusick char *domainname; 65541486Smckusick u_int len; 65643452Shibler } *uap; 65743452Shibler int *retval; 65843452Shibler { 65943452Shibler int error; 66041486Smckusick 66143452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 662*44421Skarels return (error); 66343452Shibler if (uap->len > sizeof (domainname) - 1) 664*44421Skarels return (EINVAL); 66541486Smckusick domainnamelen = uap->len; 66643452Shibler error = copyin(uap->domainname, domainname, uap->len); 66741486Smckusick domainname[domainnamelen] = 0; 668*44421Skarels return (error); 66941486Smckusick } 67041486Smckusick 67141486Smckusick #ifdef SYSVSHM 67243452Shibler hpuxshmat(p, uap, retval) 67343452Shibler struct proc *p; 67443452Shibler int *uap, *retval; 67541486Smckusick { 676*44421Skarels return (shmat(p, uap, retval)); 67741486Smckusick } 67841486Smckusick 67943452Shibler hpuxshmctl(p, uap, retval) 68043452Shibler struct proc *p; 68143452Shibler int *uap, *retval; 68241486Smckusick { 683*44421Skarels return (shmctl(p, uap, retval)); 68441486Smckusick } 68541486Smckusick 68643452Shibler hpuxshmdt(p, uap, retval) 68743452Shibler struct proc *p; 68843452Shibler int *uap, *retval; 68941486Smckusick { 690*44421Skarels return (shmdt(p, uap, retval)); 69141486Smckusick } 69241486Smckusick 69343452Shibler hpuxshmget(p, uap, retval) 69443452Shibler struct proc *p; 69543452Shibler int *uap, *retval; 69641486Smckusick { 697*44421Skarels return (shmget(p, uap, retval)); 69841486Smckusick } 69941486Smckusick #endif 70041486Smckusick 70141486Smckusick /* 70241486Smckusick * Fake semaphore routines, just don't return an error. 70341486Smckusick * Should be adequate for starbase to run. 70441486Smckusick */ 70543452Shibler hpuxsemctl(p, uap, retval) 70643452Shibler struct proc *p; 70743452Shibler struct args { 70841486Smckusick int semid; 70941486Smckusick u_int semnum; 71041486Smckusick int cmd; 71141486Smckusick int arg; 71243452Shibler } *uap; 71343452Shibler int *retval; 71443452Shibler { 71541486Smckusick /* XXX: should do something here */ 716*44421Skarels return (0); 71741486Smckusick } 71841486Smckusick 71943452Shibler hpuxsemget(p, uap, retval) 72043452Shibler struct proc *p; 72143452Shibler struct args { 72241486Smckusick key_t key; 72341486Smckusick int nsems; 72441486Smckusick int semflg; 72543452Shibler } *uap; 72643452Shibler int *retval; 72743452Shibler { 72841486Smckusick /* XXX: should do something here */ 729*44421Skarels return (0); 73041486Smckusick } 73141486Smckusick 73243452Shibler hpuxsemop(p, uap, retval) 73343452Shibler struct proc *p; 73443452Shibler struct args { 73541486Smckusick int semid; 73641486Smckusick struct sembuf *sops; 73741486Smckusick u_int nsops; 73843452Shibler } *uap; 73943452Shibler int *retval; 74043452Shibler { 74141486Smckusick /* XXX: should do something here */ 742*44421Skarels return (0); 74341486Smckusick } 74441486Smckusick 74541486Smckusick /* convert from BSD to HPUX errno */ 74641486Smckusick bsdtohpuxerrno(err) 74741486Smckusick int err; 74841486Smckusick { 74941486Smckusick if (err < 0 || err >= NERR) 75041486Smckusick return(BERR); 75141486Smckusick return((int)bsdtohpuxerrnomap[err]); 75241486Smckusick } 75341486Smckusick 75441486Smckusick hpuxstat1(fname, hsb, follow) 75541486Smckusick char *fname; 75641486Smckusick struct hpuxstat *hsb; 75741486Smckusick int follow; 75841486Smckusick { 75941486Smckusick register struct nameidata *ndp = &u.u_nd; 76041486Smckusick struct stat sb; 76141486Smckusick int error; 76241486Smckusick 76341486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 76441486Smckusick ndp->ni_segflg = UIO_USERSPACE; 76541486Smckusick ndp->ni_dirp = fname; 76641486Smckusick if (error = namei(ndp)) 76741486Smckusick return (error); 76841486Smckusick error = vn_stat(ndp->ni_vp, &sb); 76941486Smckusick vput(ndp->ni_vp); 77041486Smckusick if (error == 0) 77141486Smckusick error = bsdtohpuxstat(&sb, hsb); 77241486Smckusick return (error); 77341486Smckusick } 77441486Smckusick 77541486Smckusick #include "grf.h" 77641486Smckusick 77741486Smckusick bsdtohpuxstat(sb, hsb) 77841486Smckusick struct stat *sb; 77941486Smckusick struct hpuxstat *hsb; 78041486Smckusick { 78141486Smckusick struct hpuxstat ds; 78241486Smckusick 78341486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 78441486Smckusick ds.hst_dev = sb->st_dev; 78541486Smckusick ds.hst_ino = (u_long)sb->st_ino; 78641486Smckusick ds.hst_mode = sb->st_mode; 78741486Smckusick ds.hst_nlink = sb->st_nlink; 78841486Smckusick ds.hst_uid = (u_short)sb->st_uid; 78941486Smckusick ds.hst_gid = (u_short)sb->st_gid; 79041486Smckusick #if NGRF > 0 79141486Smckusick /* XXX: I don't want to talk about it... */ 79241486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 79341486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 79441486Smckusick else 79541486Smckusick #endif 79641486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 79741486Smckusick ds.hst_size = sb->st_size; 79841486Smckusick ds.hst_atime = sb->st_atime; 79941486Smckusick ds.hst_mtime = sb->st_mtime; 80041486Smckusick ds.hst_ctime = sb->st_ctime; 80141486Smckusick ds.hst_blksize = sb->st_blksize; 80241486Smckusick ds.hst_blocks = sb->st_blocks; 80341486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 80441486Smckusick } 80541486Smckusick 80641486Smckusick hpuxtobsdioctl(com) 80741486Smckusick int com; 80841486Smckusick { 80941486Smckusick switch (com) { 81041486Smckusick case HPUXTIOCSLTC: 81141486Smckusick com = TIOCSLTC; break; 81241486Smckusick case HPUXTIOCGLTC: 81341486Smckusick com = TIOCGLTC; break; 81441486Smckusick case HPUXTIOCSPGRP: 81541486Smckusick com = TIOCSPGRP; break; 81641486Smckusick case HPUXTIOCGPGRP: 81741486Smckusick com = TIOCGPGRP; break; 81841486Smckusick case HPUXTIOCLBIS: 81941486Smckusick com = TIOCLBIS; break; 82041486Smckusick case HPUXTIOCLBIC: 82141486Smckusick com = TIOCLBIC; break; 82241486Smckusick case HPUXTIOCLSET: 82341486Smckusick com = TIOCLSET; break; 82441486Smckusick case HPUXTIOCLGET: 82541486Smckusick com = TIOCLGET; break; 82641486Smckusick } 82741486Smckusick return(com); 82841486Smckusick } 82941486Smckusick 83041486Smckusick /* 83141486Smckusick * HPUX ioctl system call. The differences here are: 83241486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 83341486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 83441486Smckusick * the sgttyb struct is 2 bytes longer 83541486Smckusick */ 83643452Shibler hpuxioctl(p, uap, retval) 83743452Shibler struct proc *p; 83843452Shibler register struct args { 83941486Smckusick int fdes; 84041486Smckusick int cmd; 84141486Smckusick caddr_t cmarg; 84243452Shibler } *uap; 84343452Shibler int *retval; 84443452Shibler { 84543452Shibler register struct file *fp; 84643452Shibler register int com, error; 84741486Smckusick register u_int size; 84841486Smckusick caddr_t memp = 0; 84941486Smckusick #define STK_PARAMS 128 85041486Smckusick char stkbuf[STK_PARAMS]; 85141486Smckusick caddr_t data = stkbuf; 85241486Smckusick 85341486Smckusick com = uap->cmd; 85441486Smckusick 85541486Smckusick /* XXX */ 85643452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 857*44421Skarels return (getsettty(uap->fdes, com, uap->cmarg)); 85841486Smckusick 85941486Smckusick if ((unsigned)uap->fdes >= NOFILE || 86043452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 861*44421Skarels return (EBADF); 86243452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 863*44421Skarels return (EBADF); 86441486Smckusick 86541486Smckusick /* 86641486Smckusick * Interpret high order word to find 86741486Smckusick * amount of data to be copied to/from the 86841486Smckusick * user's address space. 86941486Smckusick */ 87041486Smckusick size = IOCPARM_LEN(com); 87143452Shibler if (size > IOCPARM_MAX) 872*44421Skarels return (ENOTTY); 87341486Smckusick if (size > sizeof (stkbuf)) { 87443452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 87541486Smckusick data = memp; 87641486Smckusick } 87741486Smckusick if (com&IOC_IN) { 87841486Smckusick if (size) { 87943452Shibler error = copyin(uap->cmarg, data, (u_int)size); 88043452Shibler if (error) { 88141486Smckusick if (memp) 88241486Smckusick free(memp, M_IOCTLOPS); 883*44421Skarels return (error); 88441486Smckusick } 88541486Smckusick } else 88641486Smckusick *(caddr_t *)data = uap->cmarg; 88741486Smckusick } else if ((com&IOC_OUT) && size) 88841486Smckusick /* 88943452Shibler * Zero the buffer so the user always 89043452Shibler * gets back something deterministic. 89141486Smckusick */ 89241486Smckusick bzero(data, size); 89341486Smckusick else if (com&IOC_VOID) 89441486Smckusick *(caddr_t *)data = uap->cmarg; 89541486Smckusick 89641486Smckusick switch (com) { 89741486Smckusick 89841486Smckusick case HPUXTIOCCONS: 89941486Smckusick *(int *)data = 1; 90043452Shibler error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 90141486Smckusick break; 90241486Smckusick 90341486Smckusick /* BSD-style job control ioctls */ 90441486Smckusick case HPUXTIOCLBIS: 90541486Smckusick case HPUXTIOCLBIC: 90641486Smckusick case HPUXTIOCLSET: 90741486Smckusick *(int *)data &= HPUXLTOSTOP; 90841486Smckusick if (*(int *)data & HPUXLTOSTOP) 90941486Smckusick *(int *)data = LTOSTOP; 91041486Smckusick /* fall into */ 91141486Smckusick case HPUXTIOCLGET: 91241486Smckusick case HPUXTIOCSLTC: 91341486Smckusick case HPUXTIOCGLTC: 91441486Smckusick case HPUXTIOCSPGRP: 91541486Smckusick case HPUXTIOCGPGRP: 91643452Shibler error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 91743452Shibler if (error == 0 && com == HPUXTIOCLGET) { 91841486Smckusick *(int *)data &= LTOSTOP; 91941486Smckusick if (*(int *)data & LTOSTOP) 92041486Smckusick *(int *)data = HPUXLTOSTOP; 92141486Smckusick } 92241486Smckusick break; 92341486Smckusick 92441486Smckusick /* SYS 5 termio */ 92541486Smckusick case HPUXTCGETA: 92641486Smckusick case HPUXTCSETA: 92741486Smckusick case HPUXTCSETAW: 92841486Smckusick case HPUXTCSETAF: 92943452Shibler error = hpuxtermio(fp, com, data); 93041486Smckusick break; 93141486Smckusick 93241486Smckusick default: 93343452Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, data); 93441486Smckusick break; 93541486Smckusick } 93641486Smckusick /* 93741486Smckusick * Copy any data to user, size was 93841486Smckusick * already set and checked above. 93941486Smckusick */ 94043452Shibler if (error == 0 && (com&IOC_OUT) && size) 94143452Shibler error = copyout(data, uap->cmarg, (u_int)size); 94241486Smckusick if (memp) 94341486Smckusick free(memp, M_IOCTLOPS); 944*44421Skarels return (error); 94541486Smckusick } 94641486Smckusick 94741486Smckusick /* 94841486Smckusick * Man page lies, behaviour here is based on observed behaviour. 94941486Smckusick */ 95043452Shibler hpuxgetcontext(p, uap, retval) 95143452Shibler struct proc *p; 95243452Shibler struct args { 95341486Smckusick char *buf; 95441486Smckusick int len; 95543452Shibler } *uap; 95643452Shibler int *retval; 95743452Shibler { 95841486Smckusick int error = 0; 95941486Smckusick register int len; 96041486Smckusick 96141486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 96241486Smckusick if (len) 96341486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 96443452Shibler if (error == 0) 96543452Shibler *retval = sizeof(hpuxcontext); 966*44421Skarels return (error); 96741486Smckusick } 96841486Smckusick 96941486Smckusick /* 97041486Smckusick * XXX: simple recognition hack to see if we can make grmd work. 97141486Smckusick */ 97243452Shibler hpuxlockf(p, uap, retval) 97343452Shibler struct proc *p; 97443452Shibler struct args { 97541486Smckusick int fd; 97641486Smckusick int func; 97741486Smckusick long size; 97843452Shibler } *uap; 97943452Shibler int *retval; 98043452Shibler { 98141486Smckusick #ifdef DEBUG 98241486Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 98343452Shibler p->p_pid, uap->fd, uap->func, uap->size); 98441486Smckusick #endif 985*44421Skarels return (0); 98641486Smckusick } 98741486Smckusick 98841486Smckusick /* 98941486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 99041486Smckusick * Note we do not check the real uid or "saved" uid. 99141486Smckusick */ 99243452Shibler hpuxgetpgrp2(cp, uap, retval) 99343452Shibler struct proc *cp; 99443452Shibler register struct args { 99543452Shibler int pid; 99643452Shibler } *uap; 99743452Shibler int *retval; 99841486Smckusick { 99941486Smckusick register struct proc *p; 100041486Smckusick 100141486Smckusick if (uap->pid == 0) 100243452Shibler uap->pid = cp->p_pid; 100341486Smckusick p = pfind(uap->pid); 100443452Shibler if (p == 0) 1005*44421Skarels return (ESRCH); 100643452Shibler if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) 1007*44421Skarels return (EPERM); 100843452Shibler *retval = p->p_pgid; 1009*44421Skarels return (0); 101041486Smckusick } 101141486Smckusick 101241486Smckusick /* 101341486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 101441486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 101541486Smckusick */ 101643452Shibler hpuxsetpgrp2(p, uap, retval) 101743452Shibler struct proc *p; 101843452Shibler struct args { 101941486Smckusick int pid; 102041486Smckusick int pgrp; 102143452Shibler } *uap; 102243452Shibler int *retval; 102343452Shibler { 102441486Smckusick /* empirically determined */ 102543452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 1026*44421Skarels return (EINVAL); 1027*44421Skarels return (setpgrp(p, uap, retval)); 102841486Smckusick } 102941486Smckusick 103041486Smckusick /* 103141486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 103241486Smckusick * No apologies offered, if you don't like it, rewrite it! 103341486Smckusick */ 103441486Smckusick 103541486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 103641486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 103741486Smckusick 103841486Smckusick /* simplified FP structure */ 103941486Smckusick struct bsdfp { 104041486Smckusick int save[54]; 104141486Smckusick int reg[24]; 104241486Smckusick int ctrl[3]; 104341486Smckusick }; 104441486Smckusick 104541486Smckusick hpuxtobsduoff(off) 104641486Smckusick int *off; 104741486Smckusick { 104841486Smckusick struct hpuxfp *hp; 104941486Smckusick struct bsdfp *bp; 105041486Smckusick register u_int raddr; 105141486Smckusick 105241486Smckusick /* u_ar0 field */ 105341486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 105441486Smckusick return(UOFF(u_ar0)); 105541486Smckusick 105641486Smckusick #ifdef FPCOPROC 105741486Smckusick /* 68881 registers from PCB */ 105841486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 105941486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 106041486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 106141486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 106241486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 106341486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 106441486Smckusick #endif 106541486Smckusick 106641486Smckusick /* 106741486Smckusick * Everything else we recognize comes from the kernel stack, 106841486Smckusick * so we convert off to an absolute address (if not already) 106941486Smckusick * for simplicity. 107041486Smckusick */ 107141486Smckusick if (off < (int *)ctob(UPAGES)) 107241486Smckusick off = (int *)((u_int)off + (u_int)&u); 107341486Smckusick 107441486Smckusick /* 107541486Smckusick * 68020 registers. 107641486Smckusick * We know that the HPUX registers are in the same order as ours. 107741486Smckusick * The only difference is that their PS is 2 bytes instead of a 107841486Smckusick * padded 4 like ours throwing the alignment off. 107941486Smckusick */ 108041486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 108141486Smckusick /* 108241486Smckusick * PS: return low word and high word of PC as HP-UX would 108341486Smckusick * (e.g. &u.u_ar0[16.5]). 108441486Smckusick */ 108541486Smckusick if (off == &u.u_ar0[PS]) 108641486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 108741486Smckusick /* 108841486Smckusick * PC: off will be &u.u_ar0[16.5] 108941486Smckusick */ 109041486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 109141486Smckusick raddr = (u_int) &u.u_ar0[PC]; 109241486Smckusick /* 109341486Smckusick * D0-D7, A0-A7: easy 109441486Smckusick */ 109541486Smckusick else 109641486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 109741486Smckusick return((int)(raddr - (u_int)&u)); 109841486Smckusick } 109941486Smckusick 110041486Smckusick /* everything else */ 110141486Smckusick return(-1); 110241486Smckusick } 110341486Smckusick 110441486Smckusick /* 110541486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 110641486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 110741486Smckusick * convert the entire user struct. 110841486Smckusick */ 110941486Smckusick hpuxdumpu(vp, cred) 111041486Smckusick struct vnode *vp; 111141486Smckusick struct ucred *cred; 111241486Smckusick { 111341486Smckusick int error; 111441486Smckusick struct hpuxuser *faku; 111541486Smckusick struct bsdfp *bp; 111641486Smckusick short *foop; 111741486Smckusick 111841486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 111941486Smckusick /* 112041486Smckusick * Make sure there is no mistake about this 112141486Smckusick * being a real user structure. 112241486Smckusick */ 112341486Smckusick bzero((caddr_t)faku, ctob(1)); 112441486Smckusick /* 112541486Smckusick * Fill in the process sizes. 112641486Smckusick */ 112741486Smckusick faku->hpuxu_tsize = u.u_tsize; 112841486Smckusick faku->hpuxu_dsize = u.u_dsize; 112941486Smckusick faku->hpuxu_ssize = u.u_ssize; 113041486Smckusick /* 113141486Smckusick * Fill in the exec header for CDB. 113241486Smckusick * This was saved back in exec(). As far as I can tell CDB 113341486Smckusick * only uses this information to verify that a particular 113441486Smckusick * core file goes with a particular binary. 113541486Smckusick */ 113641486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 113741486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 113841486Smckusick /* 113941486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 114041486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 114141486Smckusick * so we have to move it up. 114241486Smckusick */ 114341486Smckusick faku->hpuxu_ar0 = u.u_ar0; 114441486Smckusick foop = (short *) u.u_ar0; 114541486Smckusick foop[32] = foop[33]; 114641486Smckusick foop[33] = foop[34]; 114741486Smckusick foop[34] = foop[35]; 114841486Smckusick #ifdef FPCOPROC 114941486Smckusick /* 115041486Smckusick * Copy 68881 registers from our PCB format to HPUX format 115141486Smckusick */ 115241486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 115341486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 115441486Smckusick sizeof(bp->save)); 115541486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 115641486Smckusick sizeof(bp->ctrl)); 115741486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 115841486Smckusick sizeof(bp->reg)); 115941486Smckusick #endif 116041486Smckusick /* 116141486Smckusick * Slay the dragon 116241486Smckusick */ 116341486Smckusick faku->hpuxu_dragon = -1; 116441486Smckusick /* 116541486Smckusick * Dump this artfully constructed page in place of the 116641486Smckusick * user struct page. 116741486Smckusick */ 116841486Smckusick error = vn_rdwr(UIO_WRITE, vp, 116941486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 117041486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 117141486Smckusick /* 117241486Smckusick * Dump the remaining UPAGES-1 pages normally 117341486Smckusick */ 117441486Smckusick if (!error) 117541486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 117641486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 117741486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 117841486Smckusick free((caddr_t)faku, M_TEMP); 117941486Smckusick return(error); 118041486Smckusick } 118141486Smckusick 118241486Smckusick /* 118341486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 118441486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 118541486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 118641486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 118741486Smckusick */ 118841486Smckusick /* #ifdef COMPAT */ 118941486Smckusick 119042088Smckusick #include "../sys/times.h" 119141486Smckusick 119241486Smckusick /* from old timeb.h */ 119341486Smckusick struct hpuxtimeb { 119441486Smckusick time_t time; 119541486Smckusick u_short millitm; 119641486Smckusick short timezone; 119741486Smckusick short dstflag; 119841486Smckusick }; 119941486Smckusick 120041486Smckusick /* ye ole stat structure */ 120141486Smckusick struct ohpuxstat { 120241486Smckusick dev_t ohst_dev; 120341486Smckusick u_short ohst_ino; 120441486Smckusick u_short ohst_mode; 120541486Smckusick short ohst_nlink; 120641486Smckusick short ohst_uid; 120741486Smckusick short ohst_gid; 120841486Smckusick dev_t ohst_rdev; 120941486Smckusick int ohst_size; 121041486Smckusick int ohst_atime; 121141486Smckusick int ohst_mtime; 121241486Smckusick int ohst_ctime; 121341486Smckusick }; 121441486Smckusick 121541486Smckusick /* 121641486Smckusick * SYS V style setpgrp() 121741486Smckusick */ 121843452Shibler ohpuxsetpgrp(p, uap, retval) 121943452Shibler register struct proc *p; 122043452Shibler int *uap, *retval; 122141486Smckusick { 122241486Smckusick if (p->p_pid != p->p_pgid) 122341486Smckusick pgmv(p, p->p_pid, 0); 122443452Shibler *retval = p->p_pgid; 122541486Smckusick } 122641486Smckusick 122743452Shibler ohpuxtime(p, uap, retval) 122843452Shibler struct proc *p; 122943452Shibler register struct args { 123043452Shibler long *tp; 123143452Shibler } *uap; 123243713Smckusick time_t *retval; 123341486Smckusick { 123443452Shibler int error; 123541486Smckusick 123641486Smckusick if (uap->tp) 123743452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 123843452Shibler sizeof (long)); 123943713Smckusick *retval = time.tv_sec; /* XXX */ 1240*44421Skarels return (error); 124141486Smckusick } 124241486Smckusick 124343452Shibler ohpuxstime(p, uap, retval) 124443452Shibler struct proc *p; 124543452Shibler register struct args { 124643452Shibler int time; 124743452Shibler } *uap; 124843452Shibler int *retval; 124941486Smckusick { 125041486Smckusick struct timeval tv; 125143452Shibler int s, error; 125241486Smckusick 125341486Smckusick tv.tv_sec = uap->time; 125441486Smckusick tv.tv_usec = 0; 125543452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 1256*44421Skarels return (error); 125741486Smckusick 125841486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 125941486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 126041486Smckusick s = splhigh(); time = tv; splx(s); 126141486Smckusick resettodr(); 1262*44421Skarels return (0); 126341486Smckusick } 126441486Smckusick 126543452Shibler ohpuxftime(p, uap, retval) 126643452Shibler struct proc *p; 126743452Shibler register struct args { 126841486Smckusick struct hpuxtimeb *tp; 126941486Smckusick } *uap; 127043452Shibler int *retval; 127143452Shibler { 127241486Smckusick struct hpuxtimeb tb; 127341486Smckusick int s; 127441486Smckusick 127541486Smckusick s = splhigh(); 127641486Smckusick tb.time = time.tv_sec; 127741486Smckusick tb.millitm = time.tv_usec / 1000; 127841486Smckusick splx(s); 127941486Smckusick tb.timezone = tz.tz_minuteswest; 128041486Smckusick tb.dstflag = tz.tz_dsttime; 1281*44421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 128241486Smckusick } 128341486Smckusick 128443452Shibler ohpuxalarm(p, uap, retval) 128543452Shibler register struct proc *p; 128643452Shibler register struct args { 128743452Shibler int deltat; 128843452Shibler } *uap; 128943452Shibler int *retval; 129041486Smckusick { 129141486Smckusick int s = splhigh(); 129241486Smckusick 129341486Smckusick untimeout(realitexpire, (caddr_t)p); 129441486Smckusick timerclear(&p->p_realtimer.it_interval); 129543452Shibler *retval = 0; 129641486Smckusick if (timerisset(&p->p_realtimer.it_value) && 129741486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 129843452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 129941486Smckusick if (uap->deltat == 0) { 130041486Smckusick timerclear(&p->p_realtimer.it_value); 130141486Smckusick splx(s); 1302*44421Skarels return (0); 130341486Smckusick } 130441486Smckusick p->p_realtimer.it_value = time; 130541486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 130641486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 130741486Smckusick splx(s); 1308*44421Skarels return (0); 130941486Smckusick } 131041486Smckusick 131143452Shibler ohpuxnice(p, uap, retval) 131243452Shibler register struct proc *p; 131343452Shibler register struct args { 131443452Shibler int niceness; 131543452Shibler } *uap; 131643452Shibler int *retval; 131741486Smckusick { 131843452Shibler int error; 131941486Smckusick 132043452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 132143452Shibler if (error == 0) 132243452Shibler *retval = p->p_nice - NZERO; 1323*44421Skarels return (error); 132441486Smckusick } 132541486Smckusick 132643452Shibler ohpuxtimes(p, uap, retval) 132743452Shibler struct proc *p; 132843452Shibler register struct args { 132943452Shibler struct tms *tmsb; 133043452Shibler } *uap; 133143713Smckusick time_t *retval; 133241486Smckusick { 133341486Smckusick struct tms atms; 133443452Shibler int error; 133541486Smckusick 133641486Smckusick atms.tms_utime = scale50(&u.u_ru.ru_utime); 133741486Smckusick atms.tms_stime = scale50(&u.u_ru.ru_stime); 133841486Smckusick atms.tms_cutime = scale50(&u.u_cru.ru_utime); 133941486Smckusick atms.tms_cstime = scale50(&u.u_cru.ru_stime); 134043452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 134143452Shibler if (error == 0) 134243713Smckusick *retval = scale50(&time) - scale50(&boottime); /* XXX */ 1343*44421Skarels return (error); 134441486Smckusick } 134541486Smckusick 134641486Smckusick scale50(tvp) 134741486Smckusick register struct timeval *tvp; 134841486Smckusick { 134941486Smckusick extern int hpuxtick; 135041486Smckusick 135141486Smckusick /* 135241486Smckusick * Doesn't exactly do what the documentation says. 135341486Smckusick * What we really do is return 50th of a second since that 135441486Smckusick * is what HZ is on all bobcats I know of. 135541486Smckusick */ 135641486Smckusick return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick)); 135741486Smckusick } 135841486Smckusick 135941486Smckusick /* 136041486Smckusick * Set IUPD and IACC times on file. 136141486Smckusick * Can't set ICHG. 136241486Smckusick */ 136343452Shibler ohpuxutime(p, uap, retval) 136443452Shibler struct proc *p; 136541486Smckusick register struct a { 136641486Smckusick char *fname; 136741486Smckusick time_t *tptr; 136843452Shibler } *uap; 136943452Shibler int *retval; 137043452Shibler { 137141486Smckusick struct vattr vattr; 137241486Smckusick time_t tv[2]; 137341486Smckusick register struct vnode *vp; 137441486Smckusick register struct nameidata *ndp = &u.u_nd; 137543452Shibler int error; 137641486Smckusick 137741486Smckusick if (uap->tptr) { 137843452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 137943452Shibler if (error) 1380*44421Skarels return (error); 138141486Smckusick } else 138241486Smckusick tv[0] = tv[1] = time.tv_sec; 138341486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 138441486Smckusick ndp->ni_segflg = UIO_USERSPACE; 138541486Smckusick ndp->ni_dirp = uap->fname; 138641486Smckusick vattr_null(&vattr); 138741486Smckusick vattr.va_atime.tv_sec = tv[0]; 138841486Smckusick vattr.va_atime.tv_usec = 0; 138941486Smckusick vattr.va_mtime.tv_sec = tv[1]; 139041486Smckusick vattr.va_mtime.tv_usec = 0; 139143452Shibler if (error = namei(ndp)) 1392*44421Skarels return (error); 139341486Smckusick vp = ndp->ni_vp; 139442154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 139543452Shibler error = EROFS; 139641486Smckusick else 139743452Shibler error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 139841486Smckusick vput(vp); 1399*44421Skarels return (error); 140041486Smckusick } 140141486Smckusick 140243452Shibler ohpuxpause(p, uap, retval) 140343452Shibler struct proc *p; 140443452Shibler int *uap, *retval; 140541486Smckusick { 140642155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 140742155Skarels /* always return EINTR rather than ERESTART... */ 1408*44421Skarels return (EINTR); 140941486Smckusick } 141041486Smckusick 141141486Smckusick /* 141241486Smckusick * The old fstat system call. 141341486Smckusick */ 141443452Shibler ohpuxfstat(p, uap, retval) 141543452Shibler struct proc *p; 141643452Shibler register struct args { 141741486Smckusick int fd; 141841486Smckusick struct ohpuxstat *sb; 141943452Shibler } *uap; 142043452Shibler int *retval; 142143452Shibler { 142241486Smckusick struct file *fp; 142341486Smckusick 142443452Shibler if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) 1425*44421Skarels return (EBADF); 142643452Shibler if (fp->f_type != DTYPE_VNODE) 1427*44421Skarels return (EINVAL); 1428*44421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 142941486Smckusick } 143041486Smckusick 143141486Smckusick /* 143241486Smckusick * Old stat system call. This version follows links. 143341486Smckusick */ 143443452Shibler ohpuxstat(p, uap, retval) 143543452Shibler struct proc *p; 143643452Shibler register struct args { 143741486Smckusick char *fname; 143841486Smckusick struct ohpuxstat *sb; 143943452Shibler } *uap; 144043452Shibler int *retval; 144143452Shibler { 144241486Smckusick register struct nameidata *ndp = &u.u_nd; 144343452Shibler int error; 144441486Smckusick 144541486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 144641486Smckusick ndp->ni_segflg = UIO_USERSPACE; 144741486Smckusick ndp->ni_dirp = uap->fname; 144843452Shibler if (error = namei(ndp)) 1449*44421Skarels return (error); 145043452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 145141486Smckusick vput(ndp->ni_vp); 1452*44421Skarels return (error); 145341486Smckusick } 145441486Smckusick 145541486Smckusick int 145641486Smckusick ohpuxstat1(vp, ub) 145741486Smckusick register struct vnode *vp; 145841486Smckusick struct ohpuxstat *ub; 145941486Smckusick { 146041486Smckusick struct ohpuxstat ds; 146141486Smckusick struct vattr vattr; 146241486Smckusick register int error; 146341486Smckusick 146441486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 146541486Smckusick if (error) 146641486Smckusick return(error); 146741486Smckusick /* 146841486Smckusick * Copy from inode table 146941486Smckusick */ 147041486Smckusick ds.ohst_dev = vattr.va_fsid; 147141486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 147241486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 147341486Smckusick ds.ohst_nlink = vattr.va_nlink; 147441486Smckusick ds.ohst_uid = (short)vattr.va_uid; 147541486Smckusick ds.ohst_gid = (short)vattr.va_gid; 147641486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 147741486Smckusick ds.ohst_size = (int)vattr.va_size; 147841486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 147941486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 148041486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 148141486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 148241486Smckusick } 148341486Smckusick /* #endif */ 148441486Smckusick 148541486Smckusick #endif 1486