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*42352Smckusick * @(#)hpux_compat.c 7.5 (Berkeley) 05/25/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Various HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2341486Smckusick #include "param.h" 2441486Smckusick #include "systm.h" 2541486Smckusick #include "syscontext.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 8841486Smckusick notimp(code, nargs) 8941486Smckusick { 9041486Smckusick #ifdef DEBUG 9141486Smckusick int *argp = u.u_ap; 9241486Smckusick extern char *hpuxsyscallnames[]; 9341486Smckusick 9441486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9541486Smckusick if (nargs) 9641486Smckusick while (nargs--) 9741486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 9841486Smckusick else 9941486Smckusick printf(")"); 10041486Smckusick printf("\n"); 10141486Smckusick switch (unimpresponse) { 10241486Smckusick case 0: 10341486Smckusick nosys(); 10441486Smckusick break; 10541486Smckusick case 1: 10641486Smckusick u.u_error = EINVAL; 10741486Smckusick break; 10841486Smckusick } 10941486Smckusick #else 11041486Smckusick nosys(); 11141486Smckusick #endif 11241486Smckusick uprintf("HPUX system call %d not implemented\n", code); 11341486Smckusick } 11441486Smckusick 11541486Smckusick /* 11641486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 11741486Smckusick * (status pointer, options, rusage) into the kernel rather than 118*42352Smckusick * handling it in the C library stub. We also need to map any 119*42352Smckusick * termination signal from BSD to HPUX. 12041486Smckusick */ 12141486Smckusick hpuxwait3() 12241486Smckusick { 12341486Smckusick struct a { 12441486Smckusick int *status; 12541486Smckusick int options; 12641486Smckusick int rusage; 12741486Smckusick } *uap = (struct a *)u.u_ap; 12841486Smckusick 12941486Smckusick /* rusage pointer must be zero */ 13041486Smckusick if (uap->rusage) { 13141486Smckusick u.u_error = EINVAL; 13241486Smckusick return; 13341486Smckusick } 13441486Smckusick u.u_ar0[PS] = PSL_ALLCC; 13541486Smckusick u.u_ar0[R0] = uap->options; 13641486Smckusick u.u_ar0[R1] = uap->rusage; 13741486Smckusick hpuxwait(); 13841486Smckusick } 13941486Smckusick 14041486Smckusick hpuxwait() 14141486Smckusick { 14241486Smckusick int sig, *statp; 14341486Smckusick struct a { 14441486Smckusick int *status; 14541486Smckusick } *uap = (struct a *)u.u_ap; 14641486Smckusick 14741486Smckusick statp = uap->status; /* owait clobbers first arg */ 14841486Smckusick owait(); 14941486Smckusick /* 15041486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 15141486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 15241486Smckusick */ 15342155Skarels if (u.u_error == ERESTART) 15441486Smckusick u.u_error = EINTR; 15541486Smckusick if (u.u_error) 15641486Smckusick return; 15741486Smckusick sig = u.u_r.r_val2 & 0xFF; 15841486Smckusick if (sig == WSTOPPED) { 15941486Smckusick sig = (u.u_r.r_val2 >> 8) & 0xFF; 16041486Smckusick u.u_r.r_val2 = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 16141486Smckusick } else if (sig) 16241486Smckusick u.u_r.r_val2 = (u.u_r.r_val2 & 0xFF00) | 16341486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 16441486Smckusick if (statp) 16541486Smckusick if (suword((caddr_t)statp, u.u_r.r_val2)) 16641486Smckusick u.u_error = EFAULT; 16741486Smckusick } 16841486Smckusick 169*42352Smckusick hpuxwaitpid() 170*42352Smckusick { 171*42352Smckusick int sig, *statp; 172*42352Smckusick struct a { 173*42352Smckusick int pid; 174*42352Smckusick int *status; 175*42352Smckusick int options; 176*42352Smckusick struct rusage *rusage; /* wait4 arg */ 177*42352Smckusick } *uap = (struct a *)u.u_ap; 178*42352Smckusick 179*42352Smckusick uap->rusage = 0; 180*42352Smckusick wait4(); 181*42352Smckusick /* 182*42352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 183*42352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 184*42352Smckusick */ 185*42352Smckusick if (u.u_error == ERESTART) 186*42352Smckusick u.u_error = EINTR; 187*42352Smckusick if (u.u_error) 188*42352Smckusick return; 189*42352Smckusick sig = u.u_r.r_val2 & 0xFF; 190*42352Smckusick if (sig == WSTOPPED) { 191*42352Smckusick sig = (u.u_r.r_val2 >> 8) & 0xFF; 192*42352Smckusick u.u_r.r_val2 = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 193*42352Smckusick } else if (sig) 194*42352Smckusick u.u_r.r_val2 = (u.u_r.r_val2 & 0xFF00) | 195*42352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 196*42352Smckusick if (statp) 197*42352Smckusick if (suword((caddr_t)statp, u.u_r.r_val2)) 198*42352Smckusick u.u_error = EFAULT; 199*42352Smckusick } 200*42352Smckusick 20141486Smckusick /* 20241486Smckusick * Must remap some bits in the mode mask. 20341486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 20441486Smckusick * O_SYNCIO (0100000) is removed entirely. 20541486Smckusick */ 20641486Smckusick hpuxopen(scp) 20741486Smckusick register struct syscontext *scp; 20841486Smckusick { 20941486Smckusick struct a { 21041486Smckusick char *fname; 21141486Smckusick int mode; 21241486Smckusick int crtmode; 21341486Smckusick } *uap = (struct a *) scp->sc_ap; 21441486Smckusick struct nameidata *ndp = &scp->sc_nd; 21541486Smckusick int mode; 21641486Smckusick 21741486Smckusick mode = uap->mode; 21841486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 21941486Smckusick if (mode & HPUXFCREAT) { 22041486Smckusick /* 22141486Smckusick * simulate the pre-NFS behavior that opening a 22241486Smckusick * file for READ+CREATE ignores the CREATE (unless 22341486Smckusick * EXCL is set in which case we will return the 22441486Smckusick * proper error). 22541486Smckusick */ 22641486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 22741486Smckusick uap->mode |= FCREAT; 22841486Smckusick } 22941486Smckusick if (mode & HPUXFTRUNC) 23041486Smckusick uap->mode |= FTRUNC; 23141486Smckusick if (mode & HPUXFEXCL) 23241486Smckusick uap->mode |= FEXCL; 23341486Smckusick ndp->ni_segflg = UIO_USERSPACE; 23441486Smckusick ndp->ni_dirp = uap->fname; 23541486Smckusick RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp, 23641486Smckusick &scp->sc_retval1)); 23741486Smckusick } 23841486Smckusick 23941486Smckusick hpuxfcntl() 24041486Smckusick { 24141486Smckusick register struct a { 24241486Smckusick int fdes; 24341486Smckusick int cmd; 24441486Smckusick int arg; 24541486Smckusick } *uap = (struct a *)u.u_ap; 24641486Smckusick int mode; 24741486Smckusick 24841486Smckusick switch (uap->cmd) { 24941486Smckusick case F_SETFL: 25041486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 25141486Smckusick break; 25241486Smckusick case F_GETFL: 25341486Smckusick case F_DUPFD: 25441486Smckusick case F_GETFD: 25541486Smckusick case F_SETFD: 25641486Smckusick break; 25741486Smckusick default: 25841486Smckusick u.u_error = EINVAL; 25941486Smckusick return; 26041486Smckusick } 26141486Smckusick fcntl(); 26241486Smckusick if (u.u_error == 0 && uap->arg == F_GETFL) { 26341486Smckusick mode = u.u_r.r_val1; 26441486Smckusick u.u_r.r_val1 &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 26541486Smckusick if (mode & FCREAT) 26641486Smckusick u.u_r.r_val1 |= HPUXFCREAT; 26741486Smckusick if (mode & FTRUNC) 26841486Smckusick u.u_r.r_val1 |= HPUXFTRUNC; 26941486Smckusick if (mode & FEXCL) 27041486Smckusick u.u_r.r_val1 |= HPUXFEXCL; 27141486Smckusick } 27241486Smckusick } 27341486Smckusick 27441486Smckusick /* 27541486Smckusick * Read and write should return a 0 count when an operation 27641486Smckusick * on a VNODE would block, not an error. Sockets appear to 27741486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 27841486Smckusick * not entirely correct, since the behavior is only defined 27941486Smckusick * for pipes and tty type devices. 28041486Smckusick */ 28141486Smckusick hpuxread() 28241486Smckusick { 28341486Smckusick struct a { 28441486Smckusick int fd; 28541486Smckusick } *uap = (struct a *)u.u_ap; 28641486Smckusick 28741486Smckusick read(); 28841486Smckusick if (u.u_error == EWOULDBLOCK && 28941486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 29041486Smckusick u.u_error = 0; 29141486Smckusick u.u_r.r_val1 = 0; 29241486Smckusick } 29341486Smckusick } 29441486Smckusick 29541486Smckusick hpuxwrite() 29641486Smckusick { 29741486Smckusick struct a { 29841486Smckusick int fd; 29941486Smckusick } *uap = (struct a *)u.u_ap; 30041486Smckusick 30141486Smckusick write(); 30241486Smckusick if (u.u_error == EWOULDBLOCK && 30341486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 30441486Smckusick u.u_error = 0; 30541486Smckusick u.u_r.r_val1 = 0; 30641486Smckusick } 30741486Smckusick } 30841486Smckusick 30941486Smckusick hpuxreadv() 31041486Smckusick { 31141486Smckusick struct a { 31241486Smckusick int fd; 31341486Smckusick } *uap = (struct a *)u.u_ap; 31441486Smckusick 31541486Smckusick readv(); 31641486Smckusick if (u.u_error == EWOULDBLOCK && 31741486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 31841486Smckusick u.u_error = 0; 31941486Smckusick u.u_r.r_val1 = 0; 32041486Smckusick } 32141486Smckusick } 32241486Smckusick 32341486Smckusick hpuxwritev() 32441486Smckusick { 32541486Smckusick struct a { 32641486Smckusick int fd; 32741486Smckusick } *uap = (struct a *)u.u_ap; 32841486Smckusick 32941486Smckusick writev(); 33041486Smckusick if (u.u_error == EWOULDBLOCK && 33141486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 33241486Smckusick u.u_error = 0; 33341486Smckusick u.u_r.r_val1 = 0; 33441486Smckusick } 33541486Smckusick } 33641486Smckusick 33741486Smckusick /* 33841486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 33941486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 34041486Smckusick */ 34141486Smckusick hpuxdup() 34241486Smckusick { 34341486Smckusick register struct a { 34441486Smckusick int i; 34541486Smckusick } *uap = (struct a *)u.u_ap; 34641486Smckusick struct file *fp; 34741486Smckusick int j; 34841486Smckusick 34941486Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) { 35041486Smckusick u.u_error = EBADF; 35141486Smckusick return; 35241486Smckusick } 35341486Smckusick u.u_error = ufalloc(0, &j); 35441486Smckusick if (u.u_error) 35541486Smckusick return; 35641486Smckusick u.u_r.r_val1 = j; 35741486Smckusick dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 35841486Smckusick } 35941486Smckusick 36041486Smckusick hpuxuname() 36141486Smckusick { 36241486Smckusick register struct a { 36341486Smckusick struct hpuxutsname *uts; 36441486Smckusick int dev; 36541486Smckusick int request; 36641486Smckusick } *uap = (struct a *)u.u_ap; 36741486Smckusick register int i; 36841486Smckusick 36941486Smckusick switch (uap->request) { 37041486Smckusick /* uname */ 37141486Smckusick case 0: 37241486Smckusick /* fill in machine type */ 37341486Smckusick switch (machineid) { 37441486Smckusick case HP_320: 37541486Smckusick protoutsname.machine[6] = '2'; 37641486Smckusick break; 37741486Smckusick /* includes 318 and 319 */ 37841486Smckusick case HP_330: 37941486Smckusick protoutsname.machine[6] = '3'; 38041486Smckusick break; 38141486Smckusick case HP_340: 38241486Smckusick protoutsname.machine[6] = '4'; 38341486Smckusick break; 38441486Smckusick case HP_350: 38541486Smckusick protoutsname.machine[6] = '5'; 38641486Smckusick break; 38741486Smckusick case HP_360: 38841486Smckusick protoutsname.machine[6] = '6'; 38941486Smckusick break; 39041486Smckusick case HP_370: 39141486Smckusick protoutsname.machine[6] = '7'; 39241486Smckusick break; 39341486Smckusick } 39441486Smckusick /* copy hostname (sans domain) to nodename */ 39541486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 39641486Smckusick protoutsname.nodename[i] = hostname[i]; 39741486Smckusick u.u_error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 39841486Smckusick sizeof(struct hpuxutsname)); 39941486Smckusick break; 40041486Smckusick /* ustat - who cares? */ 40141486Smckusick case 2: 40241486Smckusick default: 40341486Smckusick u.u_error = EINVAL; 40441486Smckusick break; 40541486Smckusick } 40641486Smckusick } 40741486Smckusick 40841486Smckusick hpuxstat() 40941486Smckusick { 41041486Smckusick struct a { 41141486Smckusick char *fname; 41241486Smckusick struct hpuxstat *hsb; 41341486Smckusick } *uap = (struct a *)u.u_ap; 41441486Smckusick 41541486Smckusick u.u_error = hpuxstat1(uap->fname, uap->hsb, FOLLOW); 41641486Smckusick } 41741486Smckusick 41841486Smckusick hpuxlstat() 41941486Smckusick { 42041486Smckusick struct a { 42141486Smckusick char *fname; 42241486Smckusick struct hpuxstat *hsb; 42341486Smckusick } *uap = (struct a *) u.u_ap; 42441486Smckusick 42541486Smckusick u.u_error = hpuxstat1(uap->fname, uap->hsb, NOFOLLOW); 42641486Smckusick } 42741486Smckusick 42841486Smckusick hpuxfstat() 42941486Smckusick { 43041486Smckusick register struct file *fp; 43141486Smckusick register struct a { 43241486Smckusick int fdes; 43341486Smckusick struct hpuxstat *hsb; 43441486Smckusick } *uap = (struct a *)u.u_ap; 43541486Smckusick struct stat sb; 43641486Smckusick 43741486Smckusick if ((unsigned)uap->fdes >= NOFILE || 43841486Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) { 43941486Smckusick u.u_error = EBADF; 44041486Smckusick return; 44141486Smckusick } 44241486Smckusick switch (fp->f_type) { 44341486Smckusick 44441486Smckusick case DTYPE_VNODE: 44541486Smckusick u.u_error = vn_stat((struct vnode *)fp->f_data, &sb); 44641486Smckusick break; 44741486Smckusick 44841486Smckusick case DTYPE_SOCKET: 44941486Smckusick u.u_error = soo_stat((struct socket *)fp->f_data, &sb); 45041486Smckusick break; 45141486Smckusick 45241486Smckusick default: 45341486Smckusick panic("fstat"); 45441486Smckusick /*NOTREACHED*/ 45541486Smckusick } 45641486Smckusick /* is this right for sockets?? */ 45741486Smckusick if (u.u_error == 0) 45841486Smckusick u.u_error = bsdtohpuxstat(&sb, uap->hsb); 45941486Smckusick } 46041486Smckusick 46141486Smckusick hpuxulimit() 46241486Smckusick { 46341486Smckusick struct a { 46441486Smckusick int cmd; 46541486Smckusick long newlimit; 46641486Smckusick } *uap = (struct a *)u.u_ap; 46741486Smckusick struct rlimit *limp; 46841486Smckusick 46941486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 47041486Smckusick switch (uap->cmd) { 47141486Smckusick case 2: 47241486Smckusick uap->newlimit *= 512; 47341486Smckusick if (uap->newlimit > limp->rlim_max && 47441486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 47541486Smckusick break; 47641486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 47741486Smckusick /* else fall into... */ 47841486Smckusick 47941486Smckusick case 1: 48041486Smckusick u.u_r.r_off = limp->rlim_max / 512; 48141486Smckusick break; 48241486Smckusick 48341486Smckusick case 3: 48441486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 48541486Smckusick u.u_r.r_off = ctob(u.u_tsize) + limp->rlim_max; 48641486Smckusick break; 48741486Smckusick 48841486Smckusick default: 48941486Smckusick u.u_error = EINVAL; 49041486Smckusick break; 49141486Smckusick } 49241486Smckusick } 49341486Smckusick 49441486Smckusick /* 49541486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 49641486Smckusick * values -16 (high) thru -1 (low). 49741486Smckusick */ 49841486Smckusick hpuxrtprio() 49941486Smckusick { 50041486Smckusick register struct a { 50141486Smckusick int pid; 50241486Smckusick int prio; 50341486Smckusick } *uap = (struct a *)u.u_ap; 50441486Smckusick struct proc *p; 50541486Smckusick int nice; 50641486Smckusick 50741486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 50841486Smckusick uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) { 50941486Smckusick u.u_error = EINVAL; 51041486Smckusick return; 51141486Smckusick } 51241486Smckusick if (uap->pid == 0) 51341486Smckusick p = u.u_procp; 51441486Smckusick else if ((p = pfind(uap->pid)) == 0) { 51541486Smckusick u.u_error = ESRCH; 51641486Smckusick return; 51741486Smckusick } 51841486Smckusick nice = p->p_nice; 51941486Smckusick if (nice < NZERO) 52041486Smckusick u.u_r.r_val1 = (nice + 16) << 3; 52141486Smckusick else 52241486Smckusick u.u_r.r_val1 = RTPRIO_RTOFF; 52341486Smckusick switch (uap->prio) { 52441486Smckusick 52541486Smckusick case RTPRIO_NOCHG: 52641486Smckusick return; 52741486Smckusick 52841486Smckusick case RTPRIO_RTOFF: 52941486Smckusick if (nice >= NZERO) 53041486Smckusick return; 53141486Smckusick nice = NZERO; 53241486Smckusick break; 53341486Smckusick 53441486Smckusick default: 53541486Smckusick nice = (uap->prio >> 3) - 16; 53641486Smckusick break; 53741486Smckusick } 53841486Smckusick donice(p, nice); 53941486Smckusick if (u.u_error == EACCES) 54041486Smckusick u.u_error = EPERM; 54141486Smckusick } 54241486Smckusick 54341486Smckusick /* 54441486Smckusick * Kudos to HP folks for using such mnemonic names so I could figure 54541486Smckusick * out what this guy does. 54641486Smckusick */ 54741486Smckusick hpuxadvise() 54841486Smckusick { 54941486Smckusick struct a { 55041486Smckusick int arg; 55141486Smckusick } *uap = (struct a *) u.u_ap; 55241486Smckusick 55341486Smckusick switch (uap->arg) { 55441486Smckusick case 0: 55541486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 55641486Smckusick break; 55741486Smckusick case 1: 55841486Smckusick ICIA(); 55941486Smckusick break; 56041486Smckusick case 2: 56141486Smckusick DCIA(); 56241486Smckusick break; 56341486Smckusick default: 56441486Smckusick u.u_error = EINVAL; 56541486Smckusick break; 56641486Smckusick } 56741486Smckusick } 56841486Smckusick 56941486Smckusick hpuxptrace() 57041486Smckusick { 57141486Smckusick struct a { 57241486Smckusick int req; 57341486Smckusick int pid; 57441486Smckusick int *addr; 57541486Smckusick int data; 57641486Smckusick } *uap = (struct a *)u.u_ap; 57741486Smckusick 57841486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 57941486Smckusick if (uap->data) { 58041486Smckusick uap->data = hpuxtobsdsig(uap->data); 58141486Smckusick if (uap->data == 0) 58241486Smckusick uap->data = NSIG; 58341486Smckusick } 58441486Smckusick } 58541486Smckusick ptrace(); 58641486Smckusick } 58741486Smckusick 58841486Smckusick hpuxgetdomainname() 58941486Smckusick { 59041486Smckusick register struct a { 59141486Smckusick char *domainname; 59241486Smckusick u_int len; 59341486Smckusick } *uap = (struct a *)u.u_ap; 59441486Smckusick 59541486Smckusick if (uap->len > domainnamelen + 1) 59641486Smckusick uap->len = domainnamelen + 1; 59741486Smckusick u.u_error = copyout(domainname, uap->domainname, uap->len); 59841486Smckusick } 59941486Smckusick 60041486Smckusick hpuxsetdomainname() 60141486Smckusick { 60241486Smckusick register struct a { 60341486Smckusick char *domainname; 60441486Smckusick u_int len; 60541486Smckusick } *uap = (struct a *)u.u_ap; 60641486Smckusick 60741486Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 60841486Smckusick return; 60941486Smckusick if (uap->len > sizeof (domainname) - 1) { 61041486Smckusick u.u_error = EINVAL; 61141486Smckusick return; 61241486Smckusick } 61341486Smckusick domainnamelen = uap->len; 61441486Smckusick u.u_error = copyin(uap->domainname, domainname, uap->len); 61541486Smckusick domainname[domainnamelen] = 0; 61641486Smckusick } 61741486Smckusick 61841486Smckusick #ifdef SYSVSHM 61941486Smckusick hpuxshmat() 62041486Smckusick { 62141486Smckusick shmat(u.u_ap); 62241486Smckusick } 62341486Smckusick 62441486Smckusick hpuxshmctl() 62541486Smckusick { 62641486Smckusick shmctl(u.u_ap); 62741486Smckusick } 62841486Smckusick 62941486Smckusick hpuxshmdt() 63041486Smckusick { 63141486Smckusick shmdt(u.u_ap); 63241486Smckusick } 63341486Smckusick 63441486Smckusick hpuxshmget() 63541486Smckusick { 63641486Smckusick shmget(u.u_ap); 63741486Smckusick } 63841486Smckusick #endif 63941486Smckusick 64041486Smckusick /* 64141486Smckusick * Fake semaphore routines, just don't return an error. 64241486Smckusick * Should be adequate for starbase to run. 64341486Smckusick */ 64441486Smckusick hpuxsemctl() 64541486Smckusick { 64641486Smckusick struct a { 64741486Smckusick int semid; 64841486Smckusick u_int semnum; 64941486Smckusick int cmd; 65041486Smckusick int arg; 65141486Smckusick } *uap = (struct a *)u.u_ap; 65241486Smckusick 65341486Smckusick /* XXX: should do something here */ 65441486Smckusick } 65541486Smckusick 65641486Smckusick hpuxsemget() 65741486Smckusick { 65841486Smckusick struct a { 65941486Smckusick key_t key; 66041486Smckusick int nsems; 66141486Smckusick int semflg; 66241486Smckusick } *uap = (struct a *)u.u_ap; 66341486Smckusick 66441486Smckusick /* XXX: should do something here */ 66541486Smckusick } 66641486Smckusick 66741486Smckusick hpuxsemop() 66841486Smckusick { 66941486Smckusick struct a { 67041486Smckusick int semid; 67141486Smckusick struct sembuf *sops; 67241486Smckusick u_int nsops; 67341486Smckusick } *uap = (struct a *)u.u_ap; 67441486Smckusick 67541486Smckusick /* XXX: should do something here */ 67641486Smckusick } 67741486Smckusick 67841486Smckusick /* convert from BSD to HPUX errno */ 67941486Smckusick bsdtohpuxerrno(err) 68041486Smckusick int err; 68141486Smckusick { 68241486Smckusick if (err < 0 || err >= NERR) 68341486Smckusick return(BERR); 68441486Smckusick return((int)bsdtohpuxerrnomap[err]); 68541486Smckusick } 68641486Smckusick 68741486Smckusick hpuxstat1(fname, hsb, follow) 68841486Smckusick char *fname; 68941486Smckusick struct hpuxstat *hsb; 69041486Smckusick int follow; 69141486Smckusick { 69241486Smckusick register struct nameidata *ndp = &u.u_nd; 69341486Smckusick struct stat sb; 69441486Smckusick int error; 69541486Smckusick 69641486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 69741486Smckusick ndp->ni_segflg = UIO_USERSPACE; 69841486Smckusick ndp->ni_dirp = fname; 69941486Smckusick if (error = namei(ndp)) 70041486Smckusick return (error); 70141486Smckusick error = vn_stat(ndp->ni_vp, &sb); 70241486Smckusick vput(ndp->ni_vp); 70341486Smckusick if (error == 0) 70441486Smckusick error = bsdtohpuxstat(&sb, hsb); 70541486Smckusick return (error); 70641486Smckusick } 70741486Smckusick 70841486Smckusick #include "grf.h" 70941486Smckusick 71041486Smckusick bsdtohpuxstat(sb, hsb) 71141486Smckusick struct stat *sb; 71241486Smckusick struct hpuxstat *hsb; 71341486Smckusick { 71441486Smckusick struct hpuxstat ds; 71541486Smckusick 71641486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 71741486Smckusick ds.hst_dev = sb->st_dev; 71841486Smckusick ds.hst_ino = (u_long)sb->st_ino; 71941486Smckusick ds.hst_mode = sb->st_mode; 72041486Smckusick ds.hst_nlink = sb->st_nlink; 72141486Smckusick ds.hst_uid = (u_short)sb->st_uid; 72241486Smckusick ds.hst_gid = (u_short)sb->st_gid; 72341486Smckusick #if NGRF > 0 72441486Smckusick /* XXX: I don't want to talk about it... */ 72541486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 72641486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 72741486Smckusick else 72841486Smckusick #endif 72941486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 73041486Smckusick ds.hst_size = sb->st_size; 73141486Smckusick ds.hst_atime = sb->st_atime; 73241486Smckusick ds.hst_mtime = sb->st_mtime; 73341486Smckusick ds.hst_ctime = sb->st_ctime; 73441486Smckusick ds.hst_blksize = sb->st_blksize; 73541486Smckusick ds.hst_blocks = sb->st_blocks; 73641486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 73741486Smckusick } 73841486Smckusick 73941486Smckusick hpuxtobsdioctl(com) 74041486Smckusick int com; 74141486Smckusick { 74241486Smckusick switch (com) { 74341486Smckusick case HPUXTIOCSLTC: 74441486Smckusick com = TIOCSLTC; break; 74541486Smckusick case HPUXTIOCGLTC: 74641486Smckusick com = TIOCGLTC; break; 74741486Smckusick case HPUXTIOCSPGRP: 74841486Smckusick com = TIOCSPGRP; break; 74941486Smckusick case HPUXTIOCGPGRP: 75041486Smckusick com = TIOCGPGRP; break; 75141486Smckusick case HPUXTIOCLBIS: 75241486Smckusick com = TIOCLBIS; break; 75341486Smckusick case HPUXTIOCLBIC: 75441486Smckusick com = TIOCLBIC; break; 75541486Smckusick case HPUXTIOCLSET: 75641486Smckusick com = TIOCLSET; break; 75741486Smckusick case HPUXTIOCLGET: 75841486Smckusick com = TIOCLGET; break; 75941486Smckusick } 76041486Smckusick return(com); 76141486Smckusick } 76241486Smckusick 76341486Smckusick /* 76441486Smckusick * HPUX ioctl system call. The differences here are: 76541486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 76641486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 76741486Smckusick * the sgttyb struct is 2 bytes longer 76841486Smckusick */ 76941486Smckusick hpuxioctl() 77041486Smckusick { 77141486Smckusick register struct file *fp; 77241486Smckusick struct a { 77341486Smckusick int fdes; 77441486Smckusick int cmd; 77541486Smckusick caddr_t cmarg; 77641486Smckusick } *uap = (struct a *)u.u_ap; 77741486Smckusick register int com; 77841486Smckusick register u_int size; 77941486Smckusick caddr_t memp = 0; 78041486Smckusick #define STK_PARAMS 128 78141486Smckusick char stkbuf[STK_PARAMS]; 78241486Smckusick caddr_t data = stkbuf; 78341486Smckusick 78441486Smckusick com = uap->cmd; 78541486Smckusick 78641486Smckusick /* XXX */ 78741486Smckusick if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) { 78841486Smckusick getsettty(uap->fdes, com, uap->cmarg); 78941486Smckusick return; 79041486Smckusick } 79141486Smckusick 79241486Smckusick if ((unsigned)uap->fdes >= NOFILE || 79341486Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) { 79441486Smckusick u.u_error = EBADF; 79541486Smckusick return; 79641486Smckusick } 79741486Smckusick if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 79841486Smckusick u.u_error = EBADF; 79941486Smckusick return; 80041486Smckusick } 80141486Smckusick 80241486Smckusick /* 80341486Smckusick * Interpret high order word to find 80441486Smckusick * amount of data to be copied to/from the 80541486Smckusick * user's address space. 80641486Smckusick */ 80741486Smckusick size = IOCPARM_LEN(com); 80841486Smckusick if (size > IOCPARM_MAX) { 80941486Smckusick u.u_error = EFAULT; 81041486Smckusick return; 81141486Smckusick } 81241486Smckusick if (size > sizeof (stkbuf)) { 81341486Smckusick memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS, 81441486Smckusick M_WAITOK); 81541486Smckusick data = memp; 81641486Smckusick } 81741486Smckusick if (com&IOC_IN) { 81841486Smckusick if (size) { 81941486Smckusick u.u_error = copyin(uap->cmarg, data, (u_int)size); 82041486Smckusick if (u.u_error) { 82141486Smckusick if (memp) 82241486Smckusick free(memp, M_IOCTLOPS); 82341486Smckusick return; 82441486Smckusick } 82541486Smckusick } else 82641486Smckusick *(caddr_t *)data = uap->cmarg; 82741486Smckusick } else if ((com&IOC_OUT) && size) 82841486Smckusick /* 82941486Smckusick * Zero the buffer on the stack so the user 83041486Smckusick * always gets back something deterministic. 83141486Smckusick */ 83241486Smckusick bzero(data, size); 83341486Smckusick else if (com&IOC_VOID) 83441486Smckusick *(caddr_t *)data = uap->cmarg; 83541486Smckusick 83641486Smckusick switch (com) { 83741486Smckusick 83841486Smckusick case HPUXTIOCCONS: 83941486Smckusick *(int *)data = 1; 84041486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 84141486Smckusick break; 84241486Smckusick 84341486Smckusick /* BSD-style job control ioctls */ 84441486Smckusick case HPUXTIOCLBIS: 84541486Smckusick case HPUXTIOCLBIC: 84641486Smckusick case HPUXTIOCLSET: 84741486Smckusick *(int *)data &= HPUXLTOSTOP; 84841486Smckusick if (*(int *)data & HPUXLTOSTOP) 84941486Smckusick *(int *)data = LTOSTOP; 85041486Smckusick /* fall into */ 85141486Smckusick case HPUXTIOCLGET: 85241486Smckusick case HPUXTIOCSLTC: 85341486Smckusick case HPUXTIOCGLTC: 85441486Smckusick case HPUXTIOCSPGRP: 85541486Smckusick case HPUXTIOCGPGRP: 85641486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 85741486Smckusick if (u.u_error == 0 && com == HPUXTIOCLGET) { 85841486Smckusick *(int *)data &= LTOSTOP; 85941486Smckusick if (*(int *)data & LTOSTOP) 86041486Smckusick *(int *)data = HPUXLTOSTOP; 86141486Smckusick } 86241486Smckusick break; 86341486Smckusick 86441486Smckusick /* SYS 5 termio */ 86541486Smckusick case HPUXTCGETA: 86641486Smckusick case HPUXTCSETA: 86741486Smckusick case HPUXTCSETAW: 86841486Smckusick case HPUXTCSETAF: 86941486Smckusick u.u_error = hpuxtermio(fp, com, data); 87041486Smckusick break; 87141486Smckusick 87241486Smckusick default: 87341486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 87441486Smckusick break; 87541486Smckusick } 87641486Smckusick /* 87741486Smckusick * Copy any data to user, size was 87841486Smckusick * already set and checked above. 87941486Smckusick */ 88041486Smckusick if (u.u_error == 0 && (com&IOC_OUT) && size) 88141486Smckusick u.u_error = copyout(data, uap->cmarg, (u_int)size); 88241486Smckusick if (memp) 88341486Smckusick free(memp, M_IOCTLOPS); 88441486Smckusick } 88541486Smckusick 88641486Smckusick /* 88741486Smckusick * Man page lies, behaviour here is based on observed behaviour. 88841486Smckusick */ 88941486Smckusick hpuxgetcontext() 89041486Smckusick { 89141486Smckusick struct a { 89241486Smckusick char *buf; 89341486Smckusick int len; 89441486Smckusick } *uap = (struct a *)u.u_ap; 89541486Smckusick int error = 0; 89641486Smckusick register int len; 89741486Smckusick 89841486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 89941486Smckusick if (len) 90041486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 90141486Smckusick if (!error) 90241486Smckusick u.u_r.r_val1 = sizeof(hpuxcontext); 90341486Smckusick return(error); 90441486Smckusick } 90541486Smckusick 90641486Smckusick /* 90741486Smckusick * XXX: simple recognition hack to see if we can make grmd work. 90841486Smckusick */ 90941486Smckusick hpuxlockf() 91041486Smckusick { 91141486Smckusick struct a { 91241486Smckusick int fd; 91341486Smckusick int func; 91441486Smckusick long size; 91541486Smckusick } *uap = (struct a *)u.u_ap; 91641486Smckusick #ifdef DEBUG 91741486Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 91841486Smckusick u.u_procp->p_pid, uap->fd, uap->func, uap->size); 91941486Smckusick #endif 92041486Smckusick return(0); 92141486Smckusick } 92241486Smckusick 92341486Smckusick /* 92441486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 92541486Smckusick * Note we do not check the real uid or "saved" uid. 92641486Smckusick */ 92741486Smckusick hpuxgetpgrp2() 92841486Smckusick { 92941486Smckusick register struct proc *p; 93041486Smckusick register struct a { 93141486Smckusick int pid; 93241486Smckusick } *uap = (struct a *)u.u_ap; 93341486Smckusick 93441486Smckusick if (uap->pid == 0) 93541486Smckusick uap->pid = u.u_procp->p_pid; 93641486Smckusick p = pfind(uap->pid); 93741486Smckusick if (p == 0) { 93841486Smckusick u.u_error = ESRCH; 93941486Smckusick return; 94041486Smckusick } 94141486Smckusick if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) { 94241486Smckusick u.u_error = EPERM; 94341486Smckusick return; 94441486Smckusick } 94541486Smckusick u.u_r.r_val1 = p->p_pgid; 94641486Smckusick } 94741486Smckusick 94841486Smckusick /* 94941486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 95041486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 95141486Smckusick */ 95241486Smckusick hpuxsetpgrp2() 95341486Smckusick { 95441486Smckusick struct a { 95541486Smckusick int pid; 95641486Smckusick int pgrp; 95741486Smckusick } *uap = (struct a *)u.u_ap; 95841486Smckusick 95941486Smckusick /* empirically determined */ 96041486Smckusick if (uap->pgrp < 0 || uap->pgrp >= 30000) { 96141486Smckusick u.u_error = EINVAL; 96241486Smckusick return; 96341486Smckusick } 96441486Smckusick setpgrp(); 96541486Smckusick } 96641486Smckusick 96741486Smckusick /* 96841486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 96941486Smckusick * No apologies offered, if you don't like it, rewrite it! 97041486Smckusick */ 97141486Smckusick 97241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 97341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 97441486Smckusick 97541486Smckusick /* simplified FP structure */ 97641486Smckusick struct bsdfp { 97741486Smckusick int save[54]; 97841486Smckusick int reg[24]; 97941486Smckusick int ctrl[3]; 98041486Smckusick }; 98141486Smckusick 98241486Smckusick hpuxtobsduoff(off) 98341486Smckusick int *off; 98441486Smckusick { 98541486Smckusick struct hpuxfp *hp; 98641486Smckusick struct bsdfp *bp; 98741486Smckusick register u_int raddr; 98841486Smckusick 98941486Smckusick /* u_ar0 field */ 99041486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 99141486Smckusick return(UOFF(u_ar0)); 99241486Smckusick 99341486Smckusick #ifdef FPCOPROC 99441486Smckusick /* 68881 registers from PCB */ 99541486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 99641486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 99741486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 99841486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 99941486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 100041486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 100141486Smckusick #endif 100241486Smckusick 100341486Smckusick /* 100441486Smckusick * Everything else we recognize comes from the kernel stack, 100541486Smckusick * so we convert off to an absolute address (if not already) 100641486Smckusick * for simplicity. 100741486Smckusick */ 100841486Smckusick if (off < (int *)ctob(UPAGES)) 100941486Smckusick off = (int *)((u_int)off + (u_int)&u); 101041486Smckusick 101141486Smckusick /* 101241486Smckusick * 68020 registers. 101341486Smckusick * We know that the HPUX registers are in the same order as ours. 101441486Smckusick * The only difference is that their PS is 2 bytes instead of a 101541486Smckusick * padded 4 like ours throwing the alignment off. 101641486Smckusick */ 101741486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 101841486Smckusick /* 101941486Smckusick * PS: return low word and high word of PC as HP-UX would 102041486Smckusick * (e.g. &u.u_ar0[16.5]). 102141486Smckusick */ 102241486Smckusick if (off == &u.u_ar0[PS]) 102341486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 102441486Smckusick /* 102541486Smckusick * PC: off will be &u.u_ar0[16.5] 102641486Smckusick */ 102741486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 102841486Smckusick raddr = (u_int) &u.u_ar0[PC]; 102941486Smckusick /* 103041486Smckusick * D0-D7, A0-A7: easy 103141486Smckusick */ 103241486Smckusick else 103341486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 103441486Smckusick return((int)(raddr - (u_int)&u)); 103541486Smckusick } 103641486Smckusick 103741486Smckusick /* everything else */ 103841486Smckusick return(-1); 103941486Smckusick } 104041486Smckusick 104141486Smckusick /* 104241486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 104341486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 104441486Smckusick * convert the entire user struct. 104541486Smckusick */ 104641486Smckusick hpuxdumpu(vp, cred) 104741486Smckusick struct vnode *vp; 104841486Smckusick struct ucred *cred; 104941486Smckusick { 105041486Smckusick int error; 105141486Smckusick struct hpuxuser *faku; 105241486Smckusick struct bsdfp *bp; 105341486Smckusick short *foop; 105441486Smckusick 105541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 105641486Smckusick /* 105741486Smckusick * Make sure there is no mistake about this 105841486Smckusick * being a real user structure. 105941486Smckusick */ 106041486Smckusick bzero((caddr_t)faku, ctob(1)); 106141486Smckusick /* 106241486Smckusick * Fill in the process sizes. 106341486Smckusick */ 106441486Smckusick faku->hpuxu_tsize = u.u_tsize; 106541486Smckusick faku->hpuxu_dsize = u.u_dsize; 106641486Smckusick faku->hpuxu_ssize = u.u_ssize; 106741486Smckusick /* 106841486Smckusick * Fill in the exec header for CDB. 106941486Smckusick * This was saved back in exec(). As far as I can tell CDB 107041486Smckusick * only uses this information to verify that a particular 107141486Smckusick * core file goes with a particular binary. 107241486Smckusick */ 107341486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 107441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 107541486Smckusick /* 107641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 107741486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 107841486Smckusick * so we have to move it up. 107941486Smckusick */ 108041486Smckusick faku->hpuxu_ar0 = u.u_ar0; 108141486Smckusick foop = (short *) u.u_ar0; 108241486Smckusick foop[32] = foop[33]; 108341486Smckusick foop[33] = foop[34]; 108441486Smckusick foop[34] = foop[35]; 108541486Smckusick #ifdef FPCOPROC 108641486Smckusick /* 108741486Smckusick * Copy 68881 registers from our PCB format to HPUX format 108841486Smckusick */ 108941486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 109041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 109141486Smckusick sizeof(bp->save)); 109241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 109341486Smckusick sizeof(bp->ctrl)); 109441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 109541486Smckusick sizeof(bp->reg)); 109641486Smckusick #endif 109741486Smckusick /* 109841486Smckusick * Slay the dragon 109941486Smckusick */ 110041486Smckusick faku->hpuxu_dragon = -1; 110141486Smckusick /* 110241486Smckusick * Dump this artfully constructed page in place of the 110341486Smckusick * user struct page. 110441486Smckusick */ 110541486Smckusick error = vn_rdwr(UIO_WRITE, vp, 110641486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 110741486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 110841486Smckusick /* 110941486Smckusick * Dump the remaining UPAGES-1 pages normally 111041486Smckusick */ 111141486Smckusick if (!error) 111241486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 111341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 111441486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 111541486Smckusick free((caddr_t)faku, M_TEMP); 111641486Smckusick return(error); 111741486Smckusick } 111841486Smckusick 111941486Smckusick /* 112041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 112141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 112241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 112341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 112441486Smckusick */ 112541486Smckusick /* #ifdef COMPAT */ 112641486Smckusick 112742088Smckusick #include "../sys/times.h" 112841486Smckusick 112941486Smckusick /* from old timeb.h */ 113041486Smckusick struct hpuxtimeb { 113141486Smckusick time_t time; 113241486Smckusick u_short millitm; 113341486Smckusick short timezone; 113441486Smckusick short dstflag; 113541486Smckusick }; 113641486Smckusick 113741486Smckusick /* ye ole stat structure */ 113841486Smckusick struct ohpuxstat { 113941486Smckusick dev_t ohst_dev; 114041486Smckusick u_short ohst_ino; 114141486Smckusick u_short ohst_mode; 114241486Smckusick short ohst_nlink; 114341486Smckusick short ohst_uid; 114441486Smckusick short ohst_gid; 114541486Smckusick dev_t ohst_rdev; 114641486Smckusick int ohst_size; 114741486Smckusick int ohst_atime; 114841486Smckusick int ohst_mtime; 114941486Smckusick int ohst_ctime; 115041486Smckusick }; 115141486Smckusick 115241486Smckusick /* 115341486Smckusick * Right now the following two routines are the same as the 4.3 115441486Smckusick * osetuid/osetgid calls. Eventually they need to be changed to 115541486Smckusick * implement the notion of "saved" ids (whatever that means). 115641486Smckusick */ 115741486Smckusick ohpuxsetuid() 115841486Smckusick { 115941486Smckusick register uid; 116041486Smckusick register struct a { 116141486Smckusick int uid; 116241486Smckusick } *uap = (struct a *)u.u_ap; 116341486Smckusick 116441486Smckusick uid = uap->uid; 116541486Smckusick if (uid != u.u_procp->p_ruid && uid != u.u_cred->cr_uid && 116641486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 116741486Smckusick return; 116841486Smckusick if (u.u_cred->cr_ref > 1) 116941486Smckusick u.u_cred = crcopy(u.u_cred); 117041486Smckusick u.u_cred->cr_uid = uid; 117141486Smckusick u.u_procp->p_uid = uid; 117241486Smckusick u.u_procp->p_ruid = uid; 117341486Smckusick } 117441486Smckusick 117541486Smckusick ohpuxsetgid() 117641486Smckusick { 117741486Smckusick register gid; 117841486Smckusick register struct a { 117941486Smckusick int gid; 118041486Smckusick } *uap = (struct a *)u.u_ap; 118141486Smckusick 118241486Smckusick gid = uap->gid; 118341486Smckusick if (u.u_procp->p_rgid != gid && u.u_cred->cr_groups[0] != gid && 118441486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 118541486Smckusick return; 118641486Smckusick if (u.u_cred->cr_ref > 1) 118741486Smckusick u.u_cred = crcopy(u.u_cred); 118841486Smckusick u.u_procp->p_rgid = gid; 118941486Smckusick u.u_cred->cr_groups[0] = gid; 119041486Smckusick } 119141486Smckusick 119241486Smckusick /* 119341486Smckusick * SYS V style setpgrp() 119441486Smckusick */ 119541486Smckusick ohpuxsetpgrp() 119641486Smckusick { 119741486Smckusick register struct proc *p = u.u_procp; 119841486Smckusick 119941486Smckusick if (p->p_pid != p->p_pgid) 120041486Smckusick pgmv(p, p->p_pid, 0); 120141486Smckusick u.u_r.r_val1 = p->p_pgid; 120241486Smckusick } 120341486Smckusick 120441486Smckusick ohpuxtime() 120541486Smckusick { 120641486Smckusick register struct a { 120741486Smckusick long *tp; 120841486Smckusick } *uap = (struct a *)u.u_ap; 120941486Smckusick 121041486Smckusick if (uap->tp) 121141486Smckusick u.u_error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 121241486Smckusick sizeof (long)); 121341486Smckusick u.u_r.r_time = time.tv_sec; 121441486Smckusick } 121541486Smckusick 121641486Smckusick ohpuxstime() 121741486Smckusick { 121841486Smckusick register struct a { 121941486Smckusick int time; 122041486Smckusick } *uap = (struct a *)u.u_ap; 122141486Smckusick struct timeval tv; 122241486Smckusick int s; 122341486Smckusick 122441486Smckusick tv.tv_sec = uap->time; 122541486Smckusick tv.tv_usec = 0; 122641486Smckusick u.u_error = suser(u.u_cred, &u.u_acflag); 122741486Smckusick if (u.u_error) 122841486Smckusick return; 122941486Smckusick 123041486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 123141486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 123241486Smckusick s = splhigh(); time = tv; splx(s); 123341486Smckusick resettodr(); 123441486Smckusick } 123541486Smckusick 123641486Smckusick ohpuxftime() 123741486Smckusick { 123841486Smckusick register struct a { 123941486Smckusick struct hpuxtimeb *tp; 124041486Smckusick } *uap; 124141486Smckusick struct hpuxtimeb tb; 124241486Smckusick int s; 124341486Smckusick 124441486Smckusick uap = (struct a *)u.u_ap; 124541486Smckusick s = splhigh(); 124641486Smckusick tb.time = time.tv_sec; 124741486Smckusick tb.millitm = time.tv_usec / 1000; 124841486Smckusick splx(s); 124941486Smckusick tb.timezone = tz.tz_minuteswest; 125041486Smckusick tb.dstflag = tz.tz_dsttime; 125141486Smckusick u.u_error = copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)); 125241486Smckusick } 125341486Smckusick 125441486Smckusick ohpuxalarm() 125541486Smckusick { 125641486Smckusick register struct a { 125741486Smckusick int deltat; 125841486Smckusick } *uap = (struct a *)u.u_ap; 125941486Smckusick register struct proc *p = u.u_procp; 126041486Smckusick int s = splhigh(); 126141486Smckusick 126241486Smckusick untimeout(realitexpire, (caddr_t)p); 126341486Smckusick timerclear(&p->p_realtimer.it_interval); 126441486Smckusick u.u_r.r_val1 = 0; 126541486Smckusick if (timerisset(&p->p_realtimer.it_value) && 126641486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 126741486Smckusick u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec; 126841486Smckusick if (uap->deltat == 0) { 126941486Smckusick timerclear(&p->p_realtimer.it_value); 127041486Smckusick splx(s); 127141486Smckusick return; 127241486Smckusick } 127341486Smckusick p->p_realtimer.it_value = time; 127441486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 127541486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 127641486Smckusick splx(s); 127741486Smckusick } 127841486Smckusick 127941486Smckusick ohpuxnice() 128041486Smckusick { 128141486Smckusick register struct a { 128241486Smckusick int niceness; 128341486Smckusick } *uap = (struct a *)u.u_ap; 128441486Smckusick register struct proc *p = u.u_procp; 128541486Smckusick 128641486Smckusick donice(p, (p->p_nice-NZERO)+uap->niceness); 128741486Smckusick u.u_r.r_val1 = p->p_nice - NZERO; 128841486Smckusick } 128941486Smckusick 129041486Smckusick ohpuxtimes() 129141486Smckusick { 129241486Smckusick register struct a { 129341486Smckusick struct tms *tmsb; 129441486Smckusick } *uap = (struct a *)u.u_ap; 129541486Smckusick struct tms atms; 129641486Smckusick 129741486Smckusick atms.tms_utime = scale50(&u.u_ru.ru_utime); 129841486Smckusick atms.tms_stime = scale50(&u.u_ru.ru_stime); 129941486Smckusick atms.tms_cutime = scale50(&u.u_cru.ru_utime); 130041486Smckusick atms.tms_cstime = scale50(&u.u_cru.ru_stime); 130141486Smckusick u.u_error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 130241486Smckusick if (u.u_error == 0) 130341486Smckusick u.u_r.r_time = scale50(&time) - scale50(&boottime); 130441486Smckusick } 130541486Smckusick 130641486Smckusick scale50(tvp) 130741486Smckusick register struct timeval *tvp; 130841486Smckusick { 130941486Smckusick extern int hpuxtick; 131041486Smckusick 131141486Smckusick /* 131241486Smckusick * Doesn't exactly do what the documentation says. 131341486Smckusick * What we really do is return 50th of a second since that 131441486Smckusick * is what HZ is on all bobcats I know of. 131541486Smckusick */ 131641486Smckusick return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick)); 131741486Smckusick } 131841486Smckusick 131941486Smckusick /* 132041486Smckusick * Set IUPD and IACC times on file. 132141486Smckusick * Can't set ICHG. 132241486Smckusick */ 132341486Smckusick ohpuxutime() 132441486Smckusick { 132541486Smckusick register struct a { 132641486Smckusick char *fname; 132741486Smckusick time_t *tptr; 132841486Smckusick } *uap = (struct a *)u.u_ap; 132941486Smckusick struct vattr vattr; 133041486Smckusick time_t tv[2]; 133141486Smckusick register struct vnode *vp; 133241486Smckusick register struct nameidata *ndp = &u.u_nd; 133341486Smckusick 133441486Smckusick if (uap->tptr) { 133541486Smckusick u.u_error = 133641486Smckusick copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 133741486Smckusick if (u.u_error) 133841486Smckusick return; 133941486Smckusick } else 134041486Smckusick tv[0] = tv[1] = time.tv_sec; 134141486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 134241486Smckusick ndp->ni_segflg = UIO_USERSPACE; 134341486Smckusick ndp->ni_dirp = uap->fname; 134441486Smckusick vattr_null(&vattr); 134541486Smckusick vattr.va_atime.tv_sec = tv[0]; 134641486Smckusick vattr.va_atime.tv_usec = 0; 134741486Smckusick vattr.va_mtime.tv_sec = tv[1]; 134841486Smckusick vattr.va_mtime.tv_usec = 0; 134941486Smckusick if (u.u_error = namei(ndp)) 135041486Smckusick return; 135141486Smckusick vp = ndp->ni_vp; 135242154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 135341486Smckusick u.u_error = EROFS; 135441486Smckusick else 135541486Smckusick u.u_error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 135641486Smckusick vput(vp); 135741486Smckusick } 135841486Smckusick 135941486Smckusick ohpuxpause() 136041486Smckusick { 136141486Smckusick 136242155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 136342155Skarels /* always return EINTR rather than ERESTART... */ 136442155Skarels RETURN (EINTR); 136541486Smckusick } 136641486Smckusick 136741486Smckusick /* 136841486Smckusick * The old fstat system call. 136941486Smckusick */ 137041486Smckusick ohpuxfstat() 137141486Smckusick { 137241486Smckusick register struct a { 137341486Smckusick int fd; 137441486Smckusick struct ohpuxstat *sb; 137541486Smckusick } *uap = (struct a *)u.u_ap; 137641486Smckusick struct file *fp; 137741486Smckusick extern struct file *getinode(); 137841486Smckusick 137941486Smckusick if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) { 138041486Smckusick u.u_error = EBADF; 138141486Smckusick return; 138241486Smckusick } 138341486Smckusick if (fp->f_type != DTYPE_VNODE) { 138441486Smckusick u.u_error = EINVAL; 138541486Smckusick return; 138641486Smckusick } 138741486Smckusick u.u_error = ohpuxstat1((struct vnode *)fp->f_data, uap->sb); 138841486Smckusick } 138941486Smckusick 139041486Smckusick /* 139141486Smckusick * Old stat system call. This version follows links. 139241486Smckusick */ 139341486Smckusick ohpuxstat() 139441486Smckusick { 139541486Smckusick register struct a { 139641486Smckusick char *fname; 139741486Smckusick struct ohpuxstat *sb; 139841486Smckusick } *uap = (struct a *)u.u_ap; 139941486Smckusick register struct nameidata *ndp = &u.u_nd; 140041486Smckusick 140141486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 140241486Smckusick ndp->ni_segflg = UIO_USERSPACE; 140341486Smckusick ndp->ni_dirp = uap->fname; 140441486Smckusick if (u.u_error = namei(ndp)) 140541486Smckusick return; 140641486Smckusick u.u_error = ohpuxstat1(ndp->ni_vp, uap->sb); 140741486Smckusick vput(ndp->ni_vp); 140841486Smckusick } 140941486Smckusick 141041486Smckusick int 141141486Smckusick ohpuxstat1(vp, ub) 141241486Smckusick register struct vnode *vp; 141341486Smckusick struct ohpuxstat *ub; 141441486Smckusick { 141541486Smckusick struct ohpuxstat ds; 141641486Smckusick struct vattr vattr; 141741486Smckusick register int error; 141841486Smckusick 141941486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 142041486Smckusick if (error) 142141486Smckusick return(error); 142241486Smckusick /* 142341486Smckusick * Copy from inode table 142441486Smckusick */ 142541486Smckusick ds.ohst_dev = vattr.va_fsid; 142641486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 142741486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 142841486Smckusick ds.ohst_nlink = vattr.va_nlink; 142941486Smckusick ds.ohst_uid = (short)vattr.va_uid; 143041486Smckusick ds.ohst_gid = (short)vattr.va_gid; 143141486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 143241486Smckusick ds.ohst_size = (int)vattr.va_size; 143341486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 143441486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 143541486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 143641486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 143741486Smckusick } 143841486Smckusick /* #endif */ 143941486Smckusick 144041486Smckusick #endif 1441