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