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*43452Shibler * @(#)hpux_compat.c 7.7 (Berkeley) 06/22/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 88*43452Shibler notimp(p, uap, retval, code, nargs) 89*43452Shibler struct proc *p; 90*43452Shibler int *uap, *retval; 91*43452Shibler int code, nargs; 9241486Smckusick { 93*43452Shibler int error = 0; 9441486Smckusick #ifdef DEBUG 95*43452Shibler register int *argp = uap; 9641486Smckusick extern char *hpuxsyscallnames[]; 9741486Smckusick 9841486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9941486Smckusick if (nargs) 10041486Smckusick while (nargs--) 10141486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10241486Smckusick else 10341486Smckusick printf(")"); 10441486Smckusick printf("\n"); 10541486Smckusick switch (unimpresponse) { 10641486Smckusick case 0: 107*43452Shibler error = nosys(p, uap, retval); 10841486Smckusick break; 10941486Smckusick case 1: 110*43452Shibler error = EINVAL; 11141486Smckusick break; 11241486Smckusick } 11341486Smckusick #else 114*43452Shibler error = nosys(p, uap, retval); 11541486Smckusick #endif 116*43452Shibler uprintf("HP-UX system call %d not implemented\n", code); 117*43452Shibler RETURN (error); 11841486Smckusick } 11941486Smckusick 12041486Smckusick /* 12141486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 12241486Smckusick * (status pointer, options, rusage) into the kernel rather than 12342352Smckusick * handling it in the C library stub. We also need to map any 12442352Smckusick * termination signal from BSD to HPUX. 12541486Smckusick */ 126*43452Shibler hpuxwait3(p, uap, retval) 127*43452Shibler struct proc *p; 128*43452Shibler struct args { 12941486Smckusick int *status; 13041486Smckusick int options; 13141486Smckusick int rusage; 132*43452Shibler } *uap; 133*43452Shibler int *retval; 134*43452Shibler { 13541486Smckusick /* rusage pointer must be zero */ 136*43452Shibler if (uap->rusage) 137*43452Shibler RETURN (EINVAL); 13841486Smckusick u.u_ar0[PS] = PSL_ALLCC; 13941486Smckusick u.u_ar0[R0] = uap->options; 14041486Smckusick u.u_ar0[R1] = uap->rusage; 141*43452Shibler RETURN (hpuxwait(p, uap, retval)); 14241486Smckusick } 14341486Smckusick 144*43452Shibler hpuxwait(p, uap, retval) 145*43452Shibler struct proc *p; 146*43452Shibler struct args { 147*43452Shibler int *status; 148*43452Shibler } *uap; 149*43452Shibler int *retval; 15041486Smckusick { 151*43452Shibler int sig, *statp, error; 15241486Smckusick 15341486Smckusick statp = uap->status; /* owait clobbers first arg */ 154*43452Shibler error = owait(p, uap, retval); 15541486Smckusick /* 15641486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 15741486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 15841486Smckusick */ 159*43452Shibler if (error == ERESTART) 160*43452Shibler error = EINTR; 161*43452Shibler if (error) 162*43452Shibler RETURN (error); 163*43452Shibler sig = retval[1] & 0xFF; 16441486Smckusick if (sig == WSTOPPED) { 165*43452Shibler sig = (retval[1] >> 8) & 0xFF; 166*43452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 16741486Smckusick } else if (sig) 168*43452Shibler retval[1] = (retval[1] & 0xFF00) | 16941486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 17041486Smckusick if (statp) 171*43452Shibler if (suword((caddr_t)statp, retval[1])) 172*43452Shibler error = EFAULT; 173*43452Shibler RETURN (error); 17441486Smckusick } 17541486Smckusick 176*43452Shibler hpuxwaitpid(p, uap, retval) 177*43452Shibler struct proc *p; 178*43452Shibler struct args { 17942352Smckusick int pid; 18042352Smckusick int *status; 18142352Smckusick int options; 18242352Smckusick struct rusage *rusage; /* wait4 arg */ 183*43452Shibler } *uap; 184*43452Shibler int *retval; 185*43452Shibler { 186*43452Shibler int sig, *statp, error; 18742352Smckusick 18842352Smckusick uap->rusage = 0; 189*43452Shibler error = wait4(p, uap, retval); 19042352Smckusick /* 19142352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 19242352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 19342352Smckusick */ 194*43452Shibler if (error == ERESTART) 195*43452Shibler error = EINTR; 196*43452Shibler if (error) 197*43452Shibler RETURN (error); 198*43452Shibler sig = retval[1] & 0xFF; 19942352Smckusick if (sig == WSTOPPED) { 200*43452Shibler sig = (retval[1] >> 8) & 0xFF; 201*43452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 20242352Smckusick } else if (sig) 203*43452Shibler retval[1] = (retval[1] & 0xFF00) | 20442352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 20542352Smckusick if (statp) 206*43452Shibler if (suword((caddr_t)statp, retval[1])) 207*43452Shibler error = EFAULT; 208*43452Shibler RETURN (error); 20942352Smckusick } 21042352Smckusick 21141486Smckusick /* 21241486Smckusick * Must remap some bits in the mode mask. 21341486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 21441486Smckusick * O_SYNCIO (0100000) is removed entirely. 21541486Smckusick */ 21643067Skarels hpuxopen(p, uap, retval) 21743067Skarels struct proc *p; 218*43452Shibler register struct args { 21941486Smckusick char *fname; 22041486Smckusick int mode; 22141486Smckusick int crtmode; 22243067Skarels } *uap; 22343067Skarels int *retval; 22443067Skarels { 22541486Smckusick int mode; 22641486Smckusick 22741486Smckusick mode = uap->mode; 22841486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 22941486Smckusick if (mode & HPUXFCREAT) { 23041486Smckusick /* 23141486Smckusick * simulate the pre-NFS behavior that opening a 23241486Smckusick * file for READ+CREATE ignores the CREATE (unless 23341486Smckusick * EXCL is set in which case we will return the 23441486Smckusick * proper error). 23541486Smckusick */ 23641486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 23741486Smckusick uap->mode |= FCREAT; 23841486Smckusick } 23941486Smckusick if (mode & HPUXFTRUNC) 24041486Smckusick uap->mode |= FTRUNC; 24141486Smckusick if (mode & HPUXFEXCL) 24241486Smckusick uap->mode |= FEXCL; 24343067Skarels RETURN (open(p, uap, retval)); 24441486Smckusick } 24541486Smckusick 246*43452Shibler hpuxfcntl(p, uap, retval) 247*43452Shibler struct proc *p; 248*43452Shibler register struct args { 24941486Smckusick int fdes; 25041486Smckusick int cmd; 25141486Smckusick int arg; 252*43452Shibler } *uap; 253*43452Shibler int *retval; 254*43452Shibler { 255*43452Shibler int mode, error; 25641486Smckusick 25741486Smckusick switch (uap->cmd) { 25841486Smckusick case F_SETFL: 25941486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 26041486Smckusick break; 26141486Smckusick case F_GETFL: 26241486Smckusick case F_DUPFD: 26341486Smckusick case F_GETFD: 26441486Smckusick case F_SETFD: 26541486Smckusick break; 26641486Smckusick default: 267*43452Shibler RETURN (EINVAL); 26841486Smckusick } 269*43452Shibler error = fcntl(p, uap, retval); 270*43452Shibler if (error == 0 && uap->arg == F_GETFL) { 271*43452Shibler mode = *retval; 272*43452Shibler *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 27341486Smckusick if (mode & FCREAT) 274*43452Shibler *retval |= HPUXFCREAT; 27541486Smckusick if (mode & FTRUNC) 276*43452Shibler *retval |= HPUXFTRUNC; 27741486Smckusick if (mode & FEXCL) 278*43452Shibler *retval |= HPUXFEXCL; 27941486Smckusick } 280*43452Shibler RETURN (error); 28141486Smckusick } 28241486Smckusick 28341486Smckusick /* 28441486Smckusick * Read and write should return a 0 count when an operation 28541486Smckusick * on a VNODE would block, not an error. Sockets appear to 28641486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 28741486Smckusick * not entirely correct, since the behavior is only defined 28841486Smckusick * for pipes and tty type devices. 28941486Smckusick */ 290*43452Shibler hpuxread(p, uap, retval) 291*43452Shibler struct proc *p; 292*43452Shibler struct args { 293*43452Shibler int fd; 294*43452Shibler } *uap; 295*43452Shibler int *retval; 29641486Smckusick { 297*43452Shibler int error; 29841486Smckusick 299*43452Shibler error = read(p, uap, retval); 300*43452Shibler if (error == EWOULDBLOCK && 30141486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 302*43452Shibler error = 0; 303*43452Shibler *retval = 0; 30441486Smckusick } 305*43452Shibler RETURN (error); 30641486Smckusick } 30741486Smckusick 308*43452Shibler hpuxwrite(p, uap, retval) 309*43452Shibler struct proc *p; 310*43452Shibler struct args { 311*43452Shibler int fd; 312*43452Shibler } *uap; 313*43452Shibler int *retval; 31441486Smckusick { 315*43452Shibler int error; 31641486Smckusick 317*43452Shibler error = write(p, uap, retval); 318*43452Shibler if (error == EWOULDBLOCK && 31941486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 320*43452Shibler error = 0; 321*43452Shibler *retval = 0; 32241486Smckusick } 323*43452Shibler RETURN (error); 32441486Smckusick } 32541486Smckusick 326*43452Shibler hpuxreadv(p, uap, retval) 327*43452Shibler struct proc *p; 328*43452Shibler struct args { 329*43452Shibler int fd; 330*43452Shibler } *uap; 331*43452Shibler int *retval; 33241486Smckusick { 333*43452Shibler int error; 33441486Smckusick 335*43452Shibler error = readv(p, uap, retval); 336*43452Shibler if (error == EWOULDBLOCK && 33741486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 338*43452Shibler error = 0; 339*43452Shibler *retval = 0; 34041486Smckusick } 341*43452Shibler RETURN (error); 34241486Smckusick } 34341486Smckusick 344*43452Shibler hpuxwritev(p, uap, retval) 345*43452Shibler struct proc *p; 346*43452Shibler struct args { 347*43452Shibler int fd; 348*43452Shibler } *uap; 349*43452Shibler int *retval; 35041486Smckusick { 351*43452Shibler int error; 35241486Smckusick 353*43452Shibler error = writev(p, uap, retval); 354*43452Shibler if (error == EWOULDBLOCK && 35541486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 356*43452Shibler error = 0; 357*43452Shibler *retval = 0; 35841486Smckusick } 359*43452Shibler RETURN (error); 36041486Smckusick } 36141486Smckusick 36241486Smckusick /* 36341486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 36441486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 36541486Smckusick */ 366*43452Shibler hpuxdup(p, uap, retval) 367*43452Shibler struct proc *p; 368*43452Shibler register struct args { 369*43452Shibler int i; 370*43452Shibler } *uap; 371*43452Shibler int *retval; 37241486Smckusick { 37341486Smckusick struct file *fp; 374*43452Shibler int fd, error; 37541486Smckusick 376*43452Shibler if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 377*43452Shibler RETURN (EBADF); 378*43452Shibler if (error = ufalloc(0, &fd)) 379*43452Shibler RETURN (error); 380*43452Shibler *retval = fd; 381*43452Shibler u.u_ofile[fd] = fp; 382*43452Shibler u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 38343067Skarels fp->f_count++; 384*43452Shibler if (fd > u.u_lastfile) 385*43452Shibler u.u_lastfile = fd; 386*43452Shibler RETURN (0); 38741486Smckusick } 38841486Smckusick 389*43452Shibler hpuxuname(p, uap, retval) 390*43452Shibler struct proc *p; 391*43452Shibler register struct args { 39241486Smckusick struct hpuxutsname *uts; 39341486Smckusick int dev; 39441486Smckusick int request; 395*43452Shibler } *uap; 396*43452Shibler int *retval; 397*43452Shibler { 39841486Smckusick register int i; 399*43452Shibler int error; 40041486Smckusick 40141486Smckusick switch (uap->request) { 40241486Smckusick /* uname */ 40341486Smckusick case 0: 40441486Smckusick /* fill in machine type */ 40541486Smckusick switch (machineid) { 40641486Smckusick case HP_320: 40741486Smckusick protoutsname.machine[6] = '2'; 40841486Smckusick break; 40941486Smckusick /* includes 318 and 319 */ 41041486Smckusick case HP_330: 41141486Smckusick protoutsname.machine[6] = '3'; 41241486Smckusick break; 41341486Smckusick case HP_340: 41441486Smckusick protoutsname.machine[6] = '4'; 41541486Smckusick break; 41641486Smckusick case HP_350: 41741486Smckusick protoutsname.machine[6] = '5'; 41841486Smckusick break; 41941486Smckusick case HP_360: 42041486Smckusick protoutsname.machine[6] = '6'; 42141486Smckusick break; 42241486Smckusick case HP_370: 42341486Smckusick protoutsname.machine[6] = '7'; 42441486Smckusick break; 425*43452Shibler /* includes 345 */ 426*43452Shibler case HP_375: 427*43452Shibler protoutsname.machine[6] = '7'; 428*43452Shibler protoutsname.machine[7] = '5'; 429*43452Shibler break; 43041486Smckusick } 43141486Smckusick /* copy hostname (sans domain) to nodename */ 43241486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 43341486Smckusick protoutsname.nodename[i] = hostname[i]; 434*43452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 435*43452Shibler sizeof(struct hpuxutsname)); 43641486Smckusick break; 43741486Smckusick /* ustat - who cares? */ 43841486Smckusick case 2: 43941486Smckusick default: 440*43452Shibler error = EINVAL; 44141486Smckusick break; 44241486Smckusick } 443*43452Shibler RETURN (error); 44441486Smckusick } 44541486Smckusick 446*43452Shibler hpuxstat(p, uap, retval) 447*43452Shibler struct proc *p; 448*43452Shibler struct args { 44941486Smckusick char *fname; 45041486Smckusick struct hpuxstat *hsb; 451*43452Shibler } *uap; 452*43452Shibler int *retval; 453*43452Shibler { 454*43452Shibler RETURN (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 45541486Smckusick } 45641486Smckusick 457*43452Shibler hpuxlstat(p, uap, retval) 458*43452Shibler struct proc *p; 459*43452Shibler struct args { 460*43452Shibler char *fname; 461*43452Shibler struct hpuxstat *hsb; 462*43452Shibler } *uap; 463*43452Shibler int *retval; 46441486Smckusick { 465*43452Shibler RETURN (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 46641486Smckusick } 46741486Smckusick 468*43452Shibler hpuxfstat(p, uap, retval) 469*43452Shibler struct proc *p; 470*43452Shibler register struct args { 471*43452Shibler int fdes; 472*43452Shibler struct hpuxstat *hsb; 473*43452Shibler } *uap; 474*43452Shibler int *retval; 47541486Smckusick { 47641486Smckusick register struct file *fp; 47741486Smckusick struct stat sb; 478*43452Shibler int error; 47941486Smckusick 48041486Smckusick if ((unsigned)uap->fdes >= NOFILE || 481*43452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 482*43452Shibler RETURN (EBADF); 483*43452Shibler 48441486Smckusick switch (fp->f_type) { 48541486Smckusick 48641486Smckusick case DTYPE_VNODE: 487*43452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 48841486Smckusick break; 48941486Smckusick 49041486Smckusick case DTYPE_SOCKET: 491*43452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 49241486Smckusick break; 49341486Smckusick 49441486Smckusick default: 49541486Smckusick panic("fstat"); 49641486Smckusick /*NOTREACHED*/ 49741486Smckusick } 49841486Smckusick /* is this right for sockets?? */ 499*43452Shibler if (error == 0) 500*43452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 501*43452Shibler RETURN (error); 50241486Smckusick } 50341486Smckusick 504*43452Shibler hpuxulimit(p, uap, retval) 505*43452Shibler struct proc *p; 506*43452Shibler register struct args { 50741486Smckusick int cmd; 50841486Smckusick long newlimit; 509*43452Shibler } *uap; 510*43452Shibler int *retval; 511*43452Shibler { 51241486Smckusick struct rlimit *limp; 513*43452Shibler int error = 0; 51441486Smckusick 51541486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 51641486Smckusick switch (uap->cmd) { 51741486Smckusick case 2: 51841486Smckusick uap->newlimit *= 512; 51941486Smckusick if (uap->newlimit > limp->rlim_max && 520*43452Shibler (error = suser(u.u_cred, &u.u_acflag))) 52141486Smckusick break; 52241486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 52341486Smckusick /* else fall into... */ 52441486Smckusick 52541486Smckusick case 1: 526*43452Shibler u.u_r.r_off = limp->rlim_max / 512; /* XXX */ 52741486Smckusick break; 52841486Smckusick 52941486Smckusick case 3: 53041486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 531*43452Shibler u.u_r.r_off = ctob(u.u_tsize) + limp->rlim_max; /* XXX */ 53241486Smckusick break; 53341486Smckusick 53441486Smckusick default: 535*43452Shibler error = EINVAL; 53641486Smckusick break; 53741486Smckusick } 538*43452Shibler RETURN (error); 53941486Smckusick } 54041486Smckusick 54141486Smckusick /* 54241486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 54341486Smckusick * values -16 (high) thru -1 (low). 54441486Smckusick */ 545*43452Shibler hpuxrtprio(cp, uap, retval) 546*43452Shibler struct proc *cp; 547*43452Shibler register struct args { 54841486Smckusick int pid; 54941486Smckusick int prio; 550*43452Shibler } *uap; 551*43452Shibler int *retval; 552*43452Shibler { 55341486Smckusick struct proc *p; 554*43452Shibler int nice, error; 55541486Smckusick 55641486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 557*43452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 558*43452Shibler RETURN (EINVAL); 55941486Smckusick if (uap->pid == 0) 560*43452Shibler p = cp; 561*43452Shibler else if ((p = pfind(uap->pid)) == 0) 562*43452Shibler RETURN (ESRCH); 56341486Smckusick nice = p->p_nice; 56441486Smckusick if (nice < NZERO) 565*43452Shibler *retval = (nice + 16) << 3; 56641486Smckusick else 567*43452Shibler *retval = RTPRIO_RTOFF; 56841486Smckusick switch (uap->prio) { 56941486Smckusick 57041486Smckusick case RTPRIO_NOCHG: 571*43452Shibler RETURN (0); 57241486Smckusick 57341486Smckusick case RTPRIO_RTOFF: 57441486Smckusick if (nice >= NZERO) 575*43452Shibler RETURN (0); 57641486Smckusick nice = NZERO; 57741486Smckusick break; 57841486Smckusick 57941486Smckusick default: 58041486Smckusick nice = (uap->prio >> 3) - 16; 58141486Smckusick break; 58241486Smckusick } 583*43452Shibler error = donice(cp, p, nice); 584*43452Shibler if (error == EACCES) 585*43452Shibler error = EPERM; 586*43452Shibler RETURN (error); 58741486Smckusick } 58841486Smckusick 589*43452Shibler hpuxadvise(p, uap, retval) 590*43452Shibler struct proc *p; 591*43452Shibler struct args { 592*43452Shibler int arg; 593*43452Shibler } *uap; 594*43452Shibler int *retval; 59541486Smckusick { 596*43452Shibler int error = 0; 59741486Smckusick 59841486Smckusick switch (uap->arg) { 59941486Smckusick case 0: 60041486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 60141486Smckusick break; 60241486Smckusick case 1: 60341486Smckusick ICIA(); 60441486Smckusick break; 60541486Smckusick case 2: 60641486Smckusick DCIA(); 60741486Smckusick break; 60841486Smckusick default: 609*43452Shibler error = EINVAL; 61041486Smckusick break; 61141486Smckusick } 612*43452Shibler RETURN (error); 61341486Smckusick } 61441486Smckusick 615*43452Shibler hpuxptrace(p, uap, retval) 616*43452Shibler struct proc *p; 617*43452Shibler struct args { 61841486Smckusick int req; 61941486Smckusick int pid; 62041486Smckusick int *addr; 62141486Smckusick int data; 622*43452Shibler } *uap; 623*43452Shibler int *retval; 624*43452Shibler { 625*43452Shibler int error; 62641486Smckusick 62741486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 62841486Smckusick if (uap->data) { 62941486Smckusick uap->data = hpuxtobsdsig(uap->data); 63041486Smckusick if (uap->data == 0) 63141486Smckusick uap->data = NSIG; 63241486Smckusick } 63341486Smckusick } 634*43452Shibler error = ptrace(p, uap, retval); 635*43452Shibler RETURN (error); 63641486Smckusick } 63741486Smckusick 638*43452Shibler hpuxgetdomainname(p, uap, retval) 639*43452Shibler struct proc *p; 640*43452Shibler register struct args { 64141486Smckusick char *domainname; 64241486Smckusick u_int len; 643*43452Shibler } *uap; 644*43452Shibler int *retval; 645*43452Shibler { 64641486Smckusick if (uap->len > domainnamelen + 1) 64741486Smckusick uap->len = domainnamelen + 1; 648*43452Shibler RETURN (copyout(domainname, uap->domainname, uap->len)); 64941486Smckusick } 65041486Smckusick 651*43452Shibler hpuxsetdomainname(p, uap, retval) 652*43452Shibler struct proc *p; 653*43452Shibler register struct args { 65441486Smckusick char *domainname; 65541486Smckusick u_int len; 656*43452Shibler } *uap; 657*43452Shibler int *retval; 658*43452Shibler { 659*43452Shibler int error; 66041486Smckusick 661*43452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 662*43452Shibler RETURN (error); 663*43452Shibler if (uap->len > sizeof (domainname) - 1) 664*43452Shibler RETURN (EINVAL); 66541486Smckusick domainnamelen = uap->len; 666*43452Shibler error = copyin(uap->domainname, domainname, uap->len); 66741486Smckusick domainname[domainnamelen] = 0; 668*43452Shibler RETURN (error); 66941486Smckusick } 67041486Smckusick 67141486Smckusick #ifdef SYSVSHM 672*43452Shibler hpuxshmat(p, uap, retval) 673*43452Shibler struct proc *p; 674*43452Shibler int *uap, *retval; 67541486Smckusick { 676*43452Shibler RETURN (shmat(p, uap, retval)); 67741486Smckusick } 67841486Smckusick 679*43452Shibler hpuxshmctl(p, uap, retval) 680*43452Shibler struct proc *p; 681*43452Shibler int *uap, *retval; 68241486Smckusick { 683*43452Shibler RETURN (shmctl(p, uap, retval)); 68441486Smckusick } 68541486Smckusick 686*43452Shibler hpuxshmdt(p, uap, retval) 687*43452Shibler struct proc *p; 688*43452Shibler int *uap, *retval; 68941486Smckusick { 690*43452Shibler RETURN (shmdt(p, uap, retval)); 69141486Smckusick } 69241486Smckusick 693*43452Shibler hpuxshmget(p, uap, retval) 694*43452Shibler struct proc *p; 695*43452Shibler int *uap, *retval; 69641486Smckusick { 697*43452Shibler RETURN (shmget(p, uap, retval)); 69841486Smckusick } 69941486Smckusick #endif 70041486Smckusick 70141486Smckusick /* 70241486Smckusick * Fake semaphore routines, just don't return an error. 70341486Smckusick * Should be adequate for starbase to run. 70441486Smckusick */ 705*43452Shibler hpuxsemctl(p, uap, retval) 706*43452Shibler struct proc *p; 707*43452Shibler struct args { 70841486Smckusick int semid; 70941486Smckusick u_int semnum; 71041486Smckusick int cmd; 71141486Smckusick int arg; 712*43452Shibler } *uap; 713*43452Shibler int *retval; 714*43452Shibler { 71541486Smckusick /* XXX: should do something here */ 716*43452Shibler RETURN (0); 71741486Smckusick } 71841486Smckusick 719*43452Shibler hpuxsemget(p, uap, retval) 720*43452Shibler struct proc *p; 721*43452Shibler struct args { 72241486Smckusick key_t key; 72341486Smckusick int nsems; 72441486Smckusick int semflg; 725*43452Shibler } *uap; 726*43452Shibler int *retval; 727*43452Shibler { 72841486Smckusick /* XXX: should do something here */ 729*43452Shibler RETURN (0); 73041486Smckusick } 73141486Smckusick 732*43452Shibler hpuxsemop(p, uap, retval) 733*43452Shibler struct proc *p; 734*43452Shibler struct args { 73541486Smckusick int semid; 73641486Smckusick struct sembuf *sops; 73741486Smckusick u_int nsops; 738*43452Shibler } *uap; 739*43452Shibler int *retval; 740*43452Shibler { 74141486Smckusick /* XXX: should do something here */ 742*43452Shibler RETURN (0); 74341486Smckusick } 74441486Smckusick 74541486Smckusick /* convert from BSD to HPUX errno */ 74641486Smckusick bsdtohpuxerrno(err) 74741486Smckusick int err; 74841486Smckusick { 74941486Smckusick if (err < 0 || err >= NERR) 75041486Smckusick return(BERR); 75141486Smckusick return((int)bsdtohpuxerrnomap[err]); 75241486Smckusick } 75341486Smckusick 75441486Smckusick hpuxstat1(fname, hsb, follow) 75541486Smckusick char *fname; 75641486Smckusick struct hpuxstat *hsb; 75741486Smckusick int follow; 75841486Smckusick { 75941486Smckusick register struct nameidata *ndp = &u.u_nd; 76041486Smckusick struct stat sb; 76141486Smckusick int error; 76241486Smckusick 76341486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 76441486Smckusick ndp->ni_segflg = UIO_USERSPACE; 76541486Smckusick ndp->ni_dirp = fname; 76641486Smckusick if (error = namei(ndp)) 76741486Smckusick return (error); 76841486Smckusick error = vn_stat(ndp->ni_vp, &sb); 76941486Smckusick vput(ndp->ni_vp); 77041486Smckusick if (error == 0) 77141486Smckusick error = bsdtohpuxstat(&sb, hsb); 77241486Smckusick return (error); 77341486Smckusick } 77441486Smckusick 77541486Smckusick #include "grf.h" 77641486Smckusick 77741486Smckusick bsdtohpuxstat(sb, hsb) 77841486Smckusick struct stat *sb; 77941486Smckusick struct hpuxstat *hsb; 78041486Smckusick { 78141486Smckusick struct hpuxstat ds; 78241486Smckusick 78341486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 78441486Smckusick ds.hst_dev = sb->st_dev; 78541486Smckusick ds.hst_ino = (u_long)sb->st_ino; 78641486Smckusick ds.hst_mode = sb->st_mode; 78741486Smckusick ds.hst_nlink = sb->st_nlink; 78841486Smckusick ds.hst_uid = (u_short)sb->st_uid; 78941486Smckusick ds.hst_gid = (u_short)sb->st_gid; 79041486Smckusick #if NGRF > 0 79141486Smckusick /* XXX: I don't want to talk about it... */ 79241486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 79341486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 79441486Smckusick else 79541486Smckusick #endif 79641486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 79741486Smckusick ds.hst_size = sb->st_size; 79841486Smckusick ds.hst_atime = sb->st_atime; 79941486Smckusick ds.hst_mtime = sb->st_mtime; 80041486Smckusick ds.hst_ctime = sb->st_ctime; 80141486Smckusick ds.hst_blksize = sb->st_blksize; 80241486Smckusick ds.hst_blocks = sb->st_blocks; 80341486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 80441486Smckusick } 80541486Smckusick 80641486Smckusick hpuxtobsdioctl(com) 80741486Smckusick int com; 80841486Smckusick { 80941486Smckusick switch (com) { 81041486Smckusick case HPUXTIOCSLTC: 81141486Smckusick com = TIOCSLTC; break; 81241486Smckusick case HPUXTIOCGLTC: 81341486Smckusick com = TIOCGLTC; break; 81441486Smckusick case HPUXTIOCSPGRP: 81541486Smckusick com = TIOCSPGRP; break; 81641486Smckusick case HPUXTIOCGPGRP: 81741486Smckusick com = TIOCGPGRP; break; 81841486Smckusick case HPUXTIOCLBIS: 81941486Smckusick com = TIOCLBIS; break; 82041486Smckusick case HPUXTIOCLBIC: 82141486Smckusick com = TIOCLBIC; break; 82241486Smckusick case HPUXTIOCLSET: 82341486Smckusick com = TIOCLSET; break; 82441486Smckusick case HPUXTIOCLGET: 82541486Smckusick com = TIOCLGET; break; 82641486Smckusick } 82741486Smckusick return(com); 82841486Smckusick } 82941486Smckusick 83041486Smckusick /* 83141486Smckusick * HPUX ioctl system call. The differences here are: 83241486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 83341486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 83441486Smckusick * the sgttyb struct is 2 bytes longer 83541486Smckusick */ 836*43452Shibler hpuxioctl(p, uap, retval) 837*43452Shibler struct proc *p; 838*43452Shibler register struct args { 83941486Smckusick int fdes; 84041486Smckusick int cmd; 84141486Smckusick caddr_t cmarg; 842*43452Shibler } *uap; 843*43452Shibler int *retval; 844*43452Shibler { 845*43452Shibler register struct file *fp; 846*43452Shibler register int com, error; 84741486Smckusick register u_int size; 84841486Smckusick caddr_t memp = 0; 84941486Smckusick #define STK_PARAMS 128 85041486Smckusick char stkbuf[STK_PARAMS]; 85141486Smckusick caddr_t data = stkbuf; 85241486Smckusick 85341486Smckusick com = uap->cmd; 85441486Smckusick 85541486Smckusick /* XXX */ 856*43452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 857*43452Shibler RETURN (getsettty(uap->fdes, com, uap->cmarg)); 85841486Smckusick 85941486Smckusick if ((unsigned)uap->fdes >= NOFILE || 860*43452Shibler (fp = u.u_ofile[uap->fdes]) == NULL) 861*43452Shibler RETURN (EBADF); 862*43452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 863*43452Shibler RETURN (EBADF); 86441486Smckusick 86541486Smckusick /* 86641486Smckusick * Interpret high order word to find 86741486Smckusick * amount of data to be copied to/from the 86841486Smckusick * user's address space. 86941486Smckusick */ 87041486Smckusick size = IOCPARM_LEN(com); 871*43452Shibler if (size > IOCPARM_MAX) 872*43452Shibler RETURN (ENOTTY); 87341486Smckusick if (size > sizeof (stkbuf)) { 874*43452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 87541486Smckusick data = memp; 87641486Smckusick } 87741486Smckusick if (com&IOC_IN) { 87841486Smckusick if (size) { 879*43452Shibler error = copyin(uap->cmarg, data, (u_int)size); 880*43452Shibler if (error) { 88141486Smckusick if (memp) 88241486Smckusick free(memp, M_IOCTLOPS); 883*43452Shibler RETURN (error); 88441486Smckusick } 88541486Smckusick } else 88641486Smckusick *(caddr_t *)data = uap->cmarg; 88741486Smckusick } else if ((com&IOC_OUT) && size) 88841486Smckusick /* 889*43452Shibler * Zero the buffer so the user always 890*43452Shibler * gets back something deterministic. 89141486Smckusick */ 89241486Smckusick bzero(data, size); 89341486Smckusick else if (com&IOC_VOID) 89441486Smckusick *(caddr_t *)data = uap->cmarg; 89541486Smckusick 89641486Smckusick switch (com) { 89741486Smckusick 89841486Smckusick case HPUXTIOCCONS: 89941486Smckusick *(int *)data = 1; 900*43452Shibler error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 90141486Smckusick break; 90241486Smckusick 90341486Smckusick /* BSD-style job control ioctls */ 90441486Smckusick case HPUXTIOCLBIS: 90541486Smckusick case HPUXTIOCLBIC: 90641486Smckusick case HPUXTIOCLSET: 90741486Smckusick *(int *)data &= HPUXLTOSTOP; 90841486Smckusick if (*(int *)data & HPUXLTOSTOP) 90941486Smckusick *(int *)data = LTOSTOP; 91041486Smckusick /* fall into */ 91141486Smckusick case HPUXTIOCLGET: 91241486Smckusick case HPUXTIOCSLTC: 91341486Smckusick case HPUXTIOCGLTC: 91441486Smckusick case HPUXTIOCSPGRP: 91541486Smckusick case HPUXTIOCGPGRP: 916*43452Shibler error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 917*43452Shibler if (error == 0 && com == HPUXTIOCLGET) { 91841486Smckusick *(int *)data &= LTOSTOP; 91941486Smckusick if (*(int *)data & LTOSTOP) 92041486Smckusick *(int *)data = HPUXLTOSTOP; 92141486Smckusick } 92241486Smckusick break; 92341486Smckusick 92441486Smckusick /* SYS 5 termio */ 92541486Smckusick case HPUXTCGETA: 92641486Smckusick case HPUXTCSETA: 92741486Smckusick case HPUXTCSETAW: 92841486Smckusick case HPUXTCSETAF: 929*43452Shibler error = hpuxtermio(fp, com, data); 93041486Smckusick break; 93141486Smckusick 93241486Smckusick default: 933*43452Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, data); 93441486Smckusick break; 93541486Smckusick } 93641486Smckusick /* 93741486Smckusick * Copy any data to user, size was 93841486Smckusick * already set and checked above. 93941486Smckusick */ 940*43452Shibler if (error == 0 && (com&IOC_OUT) && size) 941*43452Shibler error = copyout(data, uap->cmarg, (u_int)size); 94241486Smckusick if (memp) 94341486Smckusick free(memp, M_IOCTLOPS); 944*43452Shibler RETURN (error); 94541486Smckusick } 94641486Smckusick 94741486Smckusick /* 94841486Smckusick * Man page lies, behaviour here is based on observed behaviour. 94941486Smckusick */ 950*43452Shibler hpuxgetcontext(p, uap, retval) 951*43452Shibler struct proc *p; 952*43452Shibler struct args { 95341486Smckusick char *buf; 95441486Smckusick int len; 955*43452Shibler } *uap; 956*43452Shibler int *retval; 957*43452Shibler { 95841486Smckusick int error = 0; 95941486Smckusick register int len; 96041486Smckusick 96141486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 96241486Smckusick if (len) 96341486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 964*43452Shibler if (error == 0) 965*43452Shibler *retval = sizeof(hpuxcontext); 966*43452Shibler RETURN (error); 96741486Smckusick } 96841486Smckusick 96941486Smckusick /* 97041486Smckusick * XXX: simple recognition hack to see if we can make grmd work. 97141486Smckusick */ 972*43452Shibler hpuxlockf(p, uap, retval) 973*43452Shibler struct proc *p; 974*43452Shibler struct args { 97541486Smckusick int fd; 97641486Smckusick int func; 97741486Smckusick long size; 978*43452Shibler } *uap; 979*43452Shibler int *retval; 980*43452Shibler { 98141486Smckusick #ifdef DEBUG 98241486Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 983*43452Shibler p->p_pid, uap->fd, uap->func, uap->size); 98441486Smckusick #endif 985*43452Shibler RETURN (0); 98641486Smckusick } 98741486Smckusick 98841486Smckusick /* 98941486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 99041486Smckusick * Note we do not check the real uid or "saved" uid. 99141486Smckusick */ 992*43452Shibler hpuxgetpgrp2(cp, uap, retval) 993*43452Shibler struct proc *cp; 994*43452Shibler register struct args { 995*43452Shibler int pid; 996*43452Shibler } *uap; 997*43452Shibler int *retval; 99841486Smckusick { 99941486Smckusick register struct proc *p; 100041486Smckusick 100141486Smckusick if (uap->pid == 0) 1002*43452Shibler uap->pid = cp->p_pid; 100341486Smckusick p = pfind(uap->pid); 1004*43452Shibler if (p == 0) 1005*43452Shibler RETURN (ESRCH); 1006*43452Shibler if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) 1007*43452Shibler RETURN (EPERM); 1008*43452Shibler *retval = p->p_pgid; 1009*43452Shibler RETURN (0); 101041486Smckusick } 101141486Smckusick 101241486Smckusick /* 101341486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 101441486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 101541486Smckusick */ 1016*43452Shibler hpuxsetpgrp2(p, uap, retval) 1017*43452Shibler struct proc *p; 1018*43452Shibler struct args { 101941486Smckusick int pid; 102041486Smckusick int pgrp; 1021*43452Shibler } *uap; 1022*43452Shibler int *retval; 1023*43452Shibler { 102441486Smckusick /* empirically determined */ 1025*43452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 1026*43452Shibler RETURN (EINVAL); 1027*43452Shibler RETURN (setpgrp(p, uap, retval)); 102841486Smckusick } 102941486Smckusick 103041486Smckusick /* 103141486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 103241486Smckusick * No apologies offered, if you don't like it, rewrite it! 103341486Smckusick */ 103441486Smckusick 103541486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 103641486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 103741486Smckusick 103841486Smckusick /* simplified FP structure */ 103941486Smckusick struct bsdfp { 104041486Smckusick int save[54]; 104141486Smckusick int reg[24]; 104241486Smckusick int ctrl[3]; 104341486Smckusick }; 104441486Smckusick 104541486Smckusick hpuxtobsduoff(off) 104641486Smckusick int *off; 104741486Smckusick { 104841486Smckusick struct hpuxfp *hp; 104941486Smckusick struct bsdfp *bp; 105041486Smckusick register u_int raddr; 105141486Smckusick 105241486Smckusick /* u_ar0 field */ 105341486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 105441486Smckusick return(UOFF(u_ar0)); 105541486Smckusick 105641486Smckusick #ifdef FPCOPROC 105741486Smckusick /* 68881 registers from PCB */ 105841486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 105941486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 106041486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 106141486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 106241486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 106341486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 106441486Smckusick #endif 106541486Smckusick 106641486Smckusick /* 106741486Smckusick * Everything else we recognize comes from the kernel stack, 106841486Smckusick * so we convert off to an absolute address (if not already) 106941486Smckusick * for simplicity. 107041486Smckusick */ 107141486Smckusick if (off < (int *)ctob(UPAGES)) 107241486Smckusick off = (int *)((u_int)off + (u_int)&u); 107341486Smckusick 107441486Smckusick /* 107541486Smckusick * 68020 registers. 107641486Smckusick * We know that the HPUX registers are in the same order as ours. 107741486Smckusick * The only difference is that their PS is 2 bytes instead of a 107841486Smckusick * padded 4 like ours throwing the alignment off. 107941486Smckusick */ 108041486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 108141486Smckusick /* 108241486Smckusick * PS: return low word and high word of PC as HP-UX would 108341486Smckusick * (e.g. &u.u_ar0[16.5]). 108441486Smckusick */ 108541486Smckusick if (off == &u.u_ar0[PS]) 108641486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 108741486Smckusick /* 108841486Smckusick * PC: off will be &u.u_ar0[16.5] 108941486Smckusick */ 109041486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 109141486Smckusick raddr = (u_int) &u.u_ar0[PC]; 109241486Smckusick /* 109341486Smckusick * D0-D7, A0-A7: easy 109441486Smckusick */ 109541486Smckusick else 109641486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 109741486Smckusick return((int)(raddr - (u_int)&u)); 109841486Smckusick } 109941486Smckusick 110041486Smckusick /* everything else */ 110141486Smckusick return(-1); 110241486Smckusick } 110341486Smckusick 110441486Smckusick /* 110541486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 110641486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 110741486Smckusick * convert the entire user struct. 110841486Smckusick */ 110941486Smckusick hpuxdumpu(vp, cred) 111041486Smckusick struct vnode *vp; 111141486Smckusick struct ucred *cred; 111241486Smckusick { 111341486Smckusick int error; 111441486Smckusick struct hpuxuser *faku; 111541486Smckusick struct bsdfp *bp; 111641486Smckusick short *foop; 111741486Smckusick 111841486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 111941486Smckusick /* 112041486Smckusick * Make sure there is no mistake about this 112141486Smckusick * being a real user structure. 112241486Smckusick */ 112341486Smckusick bzero((caddr_t)faku, ctob(1)); 112441486Smckusick /* 112541486Smckusick * Fill in the process sizes. 112641486Smckusick */ 112741486Smckusick faku->hpuxu_tsize = u.u_tsize; 112841486Smckusick faku->hpuxu_dsize = u.u_dsize; 112941486Smckusick faku->hpuxu_ssize = u.u_ssize; 113041486Smckusick /* 113141486Smckusick * Fill in the exec header for CDB. 113241486Smckusick * This was saved back in exec(). As far as I can tell CDB 113341486Smckusick * only uses this information to verify that a particular 113441486Smckusick * core file goes with a particular binary. 113541486Smckusick */ 113641486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 113741486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 113841486Smckusick /* 113941486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 114041486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 114141486Smckusick * so we have to move it up. 114241486Smckusick */ 114341486Smckusick faku->hpuxu_ar0 = u.u_ar0; 114441486Smckusick foop = (short *) u.u_ar0; 114541486Smckusick foop[32] = foop[33]; 114641486Smckusick foop[33] = foop[34]; 114741486Smckusick foop[34] = foop[35]; 114841486Smckusick #ifdef FPCOPROC 114941486Smckusick /* 115041486Smckusick * Copy 68881 registers from our PCB format to HPUX format 115141486Smckusick */ 115241486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 115341486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 115441486Smckusick sizeof(bp->save)); 115541486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 115641486Smckusick sizeof(bp->ctrl)); 115741486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 115841486Smckusick sizeof(bp->reg)); 115941486Smckusick #endif 116041486Smckusick /* 116141486Smckusick * Slay the dragon 116241486Smckusick */ 116341486Smckusick faku->hpuxu_dragon = -1; 116441486Smckusick /* 116541486Smckusick * Dump this artfully constructed page in place of the 116641486Smckusick * user struct page. 116741486Smckusick */ 116841486Smckusick error = vn_rdwr(UIO_WRITE, vp, 116941486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 117041486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 117141486Smckusick /* 117241486Smckusick * Dump the remaining UPAGES-1 pages normally 117341486Smckusick */ 117441486Smckusick if (!error) 117541486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 117641486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 117741486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 117841486Smckusick free((caddr_t)faku, M_TEMP); 117941486Smckusick return(error); 118041486Smckusick } 118141486Smckusick 118241486Smckusick /* 118341486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 118441486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 118541486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 118641486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 118741486Smckusick */ 118841486Smckusick /* #ifdef COMPAT */ 118941486Smckusick 119042088Smckusick #include "../sys/times.h" 119141486Smckusick 119241486Smckusick /* from old timeb.h */ 119341486Smckusick struct hpuxtimeb { 119441486Smckusick time_t time; 119541486Smckusick u_short millitm; 119641486Smckusick short timezone; 119741486Smckusick short dstflag; 119841486Smckusick }; 119941486Smckusick 120041486Smckusick /* ye ole stat structure */ 120141486Smckusick struct ohpuxstat { 120241486Smckusick dev_t ohst_dev; 120341486Smckusick u_short ohst_ino; 120441486Smckusick u_short ohst_mode; 120541486Smckusick short ohst_nlink; 120641486Smckusick short ohst_uid; 120741486Smckusick short ohst_gid; 120841486Smckusick dev_t ohst_rdev; 120941486Smckusick int ohst_size; 121041486Smckusick int ohst_atime; 121141486Smckusick int ohst_mtime; 121241486Smckusick int ohst_ctime; 121341486Smckusick }; 121441486Smckusick 121541486Smckusick /* 121641486Smckusick * SYS V style setpgrp() 121741486Smckusick */ 1218*43452Shibler ohpuxsetpgrp(p, uap, retval) 1219*43452Shibler register struct proc *p; 1220*43452Shibler int *uap, *retval; 122141486Smckusick { 122241486Smckusick if (p->p_pid != p->p_pgid) 122341486Smckusick pgmv(p, p->p_pid, 0); 1224*43452Shibler *retval = p->p_pgid; 122541486Smckusick } 122641486Smckusick 1227*43452Shibler ohpuxtime(p, uap, retval) 1228*43452Shibler struct proc *p; 1229*43452Shibler register struct args { 1230*43452Shibler long *tp; 1231*43452Shibler } *uap; 1232*43452Shibler int *retval; 123341486Smckusick { 1234*43452Shibler int error; 123541486Smckusick 123641486Smckusick if (uap->tp) 1237*43452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1238*43452Shibler sizeof (long)); 1239*43452Shibler u.u_r.r_time = time.tv_sec; /* XXX */ 1240*43452Shibler RETURN (error); 124141486Smckusick } 124241486Smckusick 1243*43452Shibler ohpuxstime(p, uap, retval) 1244*43452Shibler struct proc *p; 1245*43452Shibler register struct args { 1246*43452Shibler int time; 1247*43452Shibler } *uap; 1248*43452Shibler int *retval; 124941486Smckusick { 125041486Smckusick struct timeval tv; 1251*43452Shibler int s, error; 125241486Smckusick 125341486Smckusick tv.tv_sec = uap->time; 125441486Smckusick tv.tv_usec = 0; 1255*43452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 1256*43452Shibler RETURN (error); 125741486Smckusick 125841486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 125941486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 126041486Smckusick s = splhigh(); time = tv; splx(s); 126141486Smckusick resettodr(); 1262*43452Shibler RETURN (0); 126341486Smckusick } 126441486Smckusick 1265*43452Shibler ohpuxftime(p, uap, retval) 1266*43452Shibler struct proc *p; 1267*43452Shibler register struct args { 126841486Smckusick struct hpuxtimeb *tp; 126941486Smckusick } *uap; 1270*43452Shibler int *retval; 1271*43452Shibler { 127241486Smckusick struct hpuxtimeb tb; 127341486Smckusick int s; 127441486Smckusick 127541486Smckusick s = splhigh(); 127641486Smckusick tb.time = time.tv_sec; 127741486Smckusick tb.millitm = time.tv_usec / 1000; 127841486Smckusick splx(s); 127941486Smckusick tb.timezone = tz.tz_minuteswest; 128041486Smckusick tb.dstflag = tz.tz_dsttime; 1281*43452Shibler RETURN (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 128241486Smckusick } 128341486Smckusick 1284*43452Shibler ohpuxalarm(p, uap, retval) 1285*43452Shibler register struct proc *p; 1286*43452Shibler register struct args { 1287*43452Shibler int deltat; 1288*43452Shibler } *uap; 1289*43452Shibler int *retval; 129041486Smckusick { 129141486Smckusick int s = splhigh(); 129241486Smckusick 129341486Smckusick untimeout(realitexpire, (caddr_t)p); 129441486Smckusick timerclear(&p->p_realtimer.it_interval); 1295*43452Shibler *retval = 0; 129641486Smckusick if (timerisset(&p->p_realtimer.it_value) && 129741486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 1298*43452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 129941486Smckusick if (uap->deltat == 0) { 130041486Smckusick timerclear(&p->p_realtimer.it_value); 130141486Smckusick splx(s); 1302*43452Shibler RETURN (0); 130341486Smckusick } 130441486Smckusick p->p_realtimer.it_value = time; 130541486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 130641486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 130741486Smckusick splx(s); 1308*43452Shibler RETURN (0); 130941486Smckusick } 131041486Smckusick 1311*43452Shibler ohpuxnice(p, uap, retval) 1312*43452Shibler register struct proc *p; 1313*43452Shibler register struct args { 1314*43452Shibler int niceness; 1315*43452Shibler } *uap; 1316*43452Shibler int *retval; 131741486Smckusick { 1318*43452Shibler int error; 131941486Smckusick 1320*43452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1321*43452Shibler if (error == 0) 1322*43452Shibler *retval = p->p_nice - NZERO; 1323*43452Shibler RETURN (error); 132441486Smckusick } 132541486Smckusick 1326*43452Shibler ohpuxtimes(p, uap, retval) 1327*43452Shibler struct proc *p; 1328*43452Shibler register struct args { 1329*43452Shibler struct tms *tmsb; 1330*43452Shibler } *uap; 1331*43452Shibler int *retval; 133241486Smckusick { 133341486Smckusick struct tms atms; 1334*43452Shibler int error; 133541486Smckusick 133641486Smckusick atms.tms_utime = scale50(&u.u_ru.ru_utime); 133741486Smckusick atms.tms_stime = scale50(&u.u_ru.ru_stime); 133841486Smckusick atms.tms_cutime = scale50(&u.u_cru.ru_utime); 133941486Smckusick atms.tms_cstime = scale50(&u.u_cru.ru_stime); 1340*43452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1341*43452Shibler if (error == 0) 1342*43452Shibler u.u_r.r_time = scale50(&time) - scale50(&boottime); /* XXX */ 1343*43452Shibler RETURN (error); 134441486Smckusick } 134541486Smckusick 134641486Smckusick scale50(tvp) 134741486Smckusick register struct timeval *tvp; 134841486Smckusick { 134941486Smckusick extern int hpuxtick; 135041486Smckusick 135141486Smckusick /* 135241486Smckusick * Doesn't exactly do what the documentation says. 135341486Smckusick * What we really do is return 50th of a second since that 135441486Smckusick * is what HZ is on all bobcats I know of. 135541486Smckusick */ 135641486Smckusick return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick)); 135741486Smckusick } 135841486Smckusick 135941486Smckusick /* 136041486Smckusick * Set IUPD and IACC times on file. 136141486Smckusick * Can't set ICHG. 136241486Smckusick */ 1363*43452Shibler ohpuxutime(p, uap, retval) 1364*43452Shibler struct proc *p; 136541486Smckusick register struct a { 136641486Smckusick char *fname; 136741486Smckusick time_t *tptr; 1368*43452Shibler } *uap; 1369*43452Shibler int *retval; 1370*43452Shibler { 137141486Smckusick struct vattr vattr; 137241486Smckusick time_t tv[2]; 137341486Smckusick register struct vnode *vp; 137441486Smckusick register struct nameidata *ndp = &u.u_nd; 1375*43452Shibler int error; 137641486Smckusick 137741486Smckusick if (uap->tptr) { 1378*43452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1379*43452Shibler if (error) 1380*43452Shibler RETURN (error); 138141486Smckusick } else 138241486Smckusick tv[0] = tv[1] = time.tv_sec; 138341486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 138441486Smckusick ndp->ni_segflg = UIO_USERSPACE; 138541486Smckusick ndp->ni_dirp = uap->fname; 138641486Smckusick vattr_null(&vattr); 138741486Smckusick vattr.va_atime.tv_sec = tv[0]; 138841486Smckusick vattr.va_atime.tv_usec = 0; 138941486Smckusick vattr.va_mtime.tv_sec = tv[1]; 139041486Smckusick vattr.va_mtime.tv_usec = 0; 1391*43452Shibler if (error = namei(ndp)) 1392*43452Shibler RETURN (error); 139341486Smckusick vp = ndp->ni_vp; 139442154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 1395*43452Shibler error = EROFS; 139641486Smckusick else 1397*43452Shibler error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 139841486Smckusick vput(vp); 1399*43452Shibler RETURN (error); 140041486Smckusick } 140141486Smckusick 1402*43452Shibler ohpuxpause(p, uap, retval) 1403*43452Shibler struct proc *p; 1404*43452Shibler int *uap, *retval; 140541486Smckusick { 140642155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 140742155Skarels /* always return EINTR rather than ERESTART... */ 140842155Skarels RETURN (EINTR); 140941486Smckusick } 141041486Smckusick 141141486Smckusick /* 141241486Smckusick * The old fstat system call. 141341486Smckusick */ 1414*43452Shibler ohpuxfstat(p, uap, retval) 1415*43452Shibler struct proc *p; 1416*43452Shibler register struct args { 141741486Smckusick int fd; 141841486Smckusick struct ohpuxstat *sb; 1419*43452Shibler } *uap; 1420*43452Shibler int *retval; 1421*43452Shibler { 142241486Smckusick struct file *fp; 142341486Smckusick 1424*43452Shibler if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) 1425*43452Shibler RETURN (EBADF); 1426*43452Shibler if (fp->f_type != DTYPE_VNODE) 1427*43452Shibler RETURN (EINVAL); 1428*43452Shibler RETURN (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 142941486Smckusick } 143041486Smckusick 143141486Smckusick /* 143241486Smckusick * Old stat system call. This version follows links. 143341486Smckusick */ 1434*43452Shibler ohpuxstat(p, uap, retval) 1435*43452Shibler struct proc *p; 1436*43452Shibler register struct args { 143741486Smckusick char *fname; 143841486Smckusick struct ohpuxstat *sb; 1439*43452Shibler } *uap; 1440*43452Shibler int *retval; 1441*43452Shibler { 144241486Smckusick register struct nameidata *ndp = &u.u_nd; 1443*43452Shibler int error; 144441486Smckusick 144541486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 144641486Smckusick ndp->ni_segflg = UIO_USERSPACE; 144741486Smckusick ndp->ni_dirp = uap->fname; 1448*43452Shibler if (error = namei(ndp)) 1449*43452Shibler RETURN (error); 1450*43452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 145141486Smckusick vput(ndp->ni_vp); 1452*43452Shibler RETURN (error); 145341486Smckusick } 145441486Smckusick 145541486Smckusick int 145641486Smckusick ohpuxstat1(vp, ub) 145741486Smckusick register struct vnode *vp; 145841486Smckusick struct ohpuxstat *ub; 145941486Smckusick { 146041486Smckusick struct ohpuxstat ds; 146141486Smckusick struct vattr vattr; 146241486Smckusick register int error; 146341486Smckusick 146441486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 146541486Smckusick if (error) 146641486Smckusick return(error); 146741486Smckusick /* 146841486Smckusick * Copy from inode table 146941486Smckusick */ 147041486Smckusick ds.ohst_dev = vattr.va_fsid; 147141486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 147241486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 147341486Smckusick ds.ohst_nlink = vattr.va_nlink; 147441486Smckusick ds.ohst_uid = (short)vattr.va_uid; 147541486Smckusick ds.ohst_gid = (short)vattr.va_gid; 147641486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 147741486Smckusick ds.ohst_size = (int)vattr.va_size; 147841486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 147941486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 148041486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 148141486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 148241486Smckusick } 148341486Smckusick /* #endif */ 148441486Smckusick 148541486Smckusick #endif 1486