1*41486Smckusick /* 2*41486Smckusick * Copyright (c) 1988 University of Utah. 3*41486Smckusick * Copyright (c) 1990 The Regents of the University of California. 4*41486Smckusick * All rights reserved. 5*41486Smckusick * 6*41486Smckusick * This code is derived from software contributed to Berkeley by 7*41486Smckusick * the Systems Programming Group of the University of Utah Computer 8*41486Smckusick * Science Department. 9*41486Smckusick * 10*41486Smckusick * %sccs.include.redist.c% 11*41486Smckusick * 12*41486Smckusick * from: Utah $Hdr: hpux_compat.c 1.33 89/08/23$ 13*41486Smckusick * 14*41486Smckusick * @(#)hpux_compat.c 7.1 (Berkeley) 05/08/90 15*41486Smckusick */ 16*41486Smckusick 17*41486Smckusick /* 18*41486Smckusick * Various HPUX compatibility routines 19*41486Smckusick */ 20*41486Smckusick 21*41486Smckusick #ifdef HPUXCOMPAT 22*41486Smckusick 23*41486Smckusick #include "param.h" 24*41486Smckusick #include "systm.h" 25*41486Smckusick #include "syscontext.h" 26*41486Smckusick #include "kernel.h" 27*41486Smckusick #include "proc.h" 28*41486Smckusick #include "buf.h" 29*41486Smckusick #include "wait.h" 30*41486Smckusick #include "file.h" 31*41486Smckusick #include "vnode.h" 32*41486Smckusick #include "ioctl.h" 33*41486Smckusick #include "uio.h" 34*41486Smckusick #include "ptrace.h" 35*41486Smckusick #include "stat.h" 36*41486Smckusick #include "syslog.h" 37*41486Smckusick #include "malloc.h" 38*41486Smckusick #include "mount.h" 39*41486Smckusick #include "ipc.h" 40*41486Smckusick 41*41486Smckusick #include "machine/cpu.h" 42*41486Smckusick #include "machine/reg.h" 43*41486Smckusick #include "machine/psl.h" 44*41486Smckusick #include "machine/vmparam.h" 45*41486Smckusick #include "hpux.h" 46*41486Smckusick #include "hpux_termio.h" 47*41486Smckusick 48*41486Smckusick #ifdef DEBUG 49*41486Smckusick int unimpresponse = 0; 50*41486Smckusick #endif 51*41486Smckusick 52*41486Smckusick /* "tick" value for HZ==50 */ 53*41486Smckusick int hpuxtick = 1000000 / 50; 54*41486Smckusick 55*41486Smckusick /* SYS5 style UTSNAME info */ 56*41486Smckusick struct hpuxutsname protoutsname = { 57*41486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 58*41486Smckusick }; 59*41486Smckusick 60*41486Smckusick /* 6.0 and later style context */ 61*41486Smckusick #ifdef FPCOPROC 62*41486Smckusick char hpuxcontext[] = 63*41486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 64*41486Smckusick #else 65*41486Smckusick char hpuxcontext[] = 66*41486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 67*41486Smckusick #endif 68*41486Smckusick 69*41486Smckusick /* YP domainname */ 70*41486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 71*41486Smckusick int domainnamelen = 7; 72*41486Smckusick 73*41486Smckusick #define NERR 79 74*41486Smckusick #define BERR 1000 75*41486Smckusick 76*41486Smckusick /* indexed by BSD errno */ 77*41486Smckusick short bsdtohpuxerrnomap[NERR] = { 78*41486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 79*41486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 80*41486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 81*41486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 82*41486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 83*41486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 84*41486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 85*41486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 86*41486Smckusick }; 87*41486Smckusick 88*41486Smckusick notimp(code, nargs) 89*41486Smckusick { 90*41486Smckusick #ifdef DEBUG 91*41486Smckusick int *argp = u.u_ap; 92*41486Smckusick extern char *hpuxsyscallnames[]; 93*41486Smckusick 94*41486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 95*41486Smckusick if (nargs) 96*41486Smckusick while (nargs--) 97*41486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 98*41486Smckusick else 99*41486Smckusick printf(")"); 100*41486Smckusick printf("\n"); 101*41486Smckusick switch (unimpresponse) { 102*41486Smckusick case 0: 103*41486Smckusick nosys(); 104*41486Smckusick break; 105*41486Smckusick case 1: 106*41486Smckusick u.u_error = EINVAL; 107*41486Smckusick break; 108*41486Smckusick } 109*41486Smckusick #else 110*41486Smckusick nosys(); 111*41486Smckusick #endif 112*41486Smckusick uprintf("HPUX system call %d not implemented\n", code); 113*41486Smckusick } 114*41486Smckusick 115*41486Smckusick /* 116*41486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 117*41486Smckusick * (status pointer, options, rusage) into the kernel rather than 118*41486Smckusick * handling it in the C library stub. We also need to map any 119*41486Smckusick * termination signal from BSD to HPUX. 120*41486Smckusick */ 121*41486Smckusick hpuxwait3() 122*41486Smckusick { 123*41486Smckusick struct a { 124*41486Smckusick int *status; 125*41486Smckusick int options; 126*41486Smckusick int rusage; 127*41486Smckusick } *uap = (struct a *)u.u_ap; 128*41486Smckusick 129*41486Smckusick /* rusage pointer must be zero */ 130*41486Smckusick if (uap->rusage) { 131*41486Smckusick u.u_error = EINVAL; 132*41486Smckusick return; 133*41486Smckusick } 134*41486Smckusick u.u_ar0[PS] = PSL_ALLCC; 135*41486Smckusick u.u_ar0[R0] = uap->options; 136*41486Smckusick u.u_ar0[R1] = uap->rusage; 137*41486Smckusick hpuxwait(); 138*41486Smckusick } 139*41486Smckusick 140*41486Smckusick hpuxwait() 141*41486Smckusick { 142*41486Smckusick int sig, *statp; 143*41486Smckusick struct a { 144*41486Smckusick int *status; 145*41486Smckusick } *uap = (struct a *)u.u_ap; 146*41486Smckusick 147*41486Smckusick statp = uap->status; /* owait clobbers first arg */ 148*41486Smckusick owait(); 149*41486Smckusick /* 150*41486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 151*41486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 152*41486Smckusick */ 153*41486Smckusick if (u.u_eosys == RESTARTSYS) { 154*41486Smckusick u.u_eosys = NORMALRETURN; 155*41486Smckusick u.u_error = EINTR; 156*41486Smckusick } 157*41486Smckusick if (u.u_error) 158*41486Smckusick return; 159*41486Smckusick sig = u.u_r.r_val2 & 0xFF; 160*41486Smckusick if (sig == WSTOPPED) { 161*41486Smckusick sig = (u.u_r.r_val2 >> 8) & 0xFF; 162*41486Smckusick u.u_r.r_val2 = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 163*41486Smckusick } else if (sig) 164*41486Smckusick u.u_r.r_val2 = (u.u_r.r_val2 & 0xFF00) | 165*41486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 166*41486Smckusick if (statp) 167*41486Smckusick if (suword((caddr_t)statp, u.u_r.r_val2)) 168*41486Smckusick u.u_error = EFAULT; 169*41486Smckusick } 170*41486Smckusick 171*41486Smckusick /* 172*41486Smckusick * Must remap some bits in the mode mask. 173*41486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 174*41486Smckusick * O_SYNCIO (0100000) is removed entirely. 175*41486Smckusick */ 176*41486Smckusick hpuxopen(scp) 177*41486Smckusick register struct syscontext *scp; 178*41486Smckusick { 179*41486Smckusick struct a { 180*41486Smckusick char *fname; 181*41486Smckusick int mode; 182*41486Smckusick int crtmode; 183*41486Smckusick } *uap = (struct a *) scp->sc_ap; 184*41486Smckusick struct nameidata *ndp = &scp->sc_nd; 185*41486Smckusick int mode; 186*41486Smckusick 187*41486Smckusick mode = uap->mode; 188*41486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 189*41486Smckusick if (mode & HPUXFCREAT) { 190*41486Smckusick /* 191*41486Smckusick * simulate the pre-NFS behavior that opening a 192*41486Smckusick * file for READ+CREATE ignores the CREATE (unless 193*41486Smckusick * EXCL is set in which case we will return the 194*41486Smckusick * proper error). 195*41486Smckusick */ 196*41486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 197*41486Smckusick uap->mode |= FCREAT; 198*41486Smckusick } 199*41486Smckusick if (mode & HPUXFTRUNC) 200*41486Smckusick uap->mode |= FTRUNC; 201*41486Smckusick if (mode & HPUXFEXCL) 202*41486Smckusick uap->mode |= FEXCL; 203*41486Smckusick ndp->ni_segflg = UIO_USERSPACE; 204*41486Smckusick ndp->ni_dirp = uap->fname; 205*41486Smckusick RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp, 206*41486Smckusick &scp->sc_retval1)); 207*41486Smckusick } 208*41486Smckusick 209*41486Smckusick hpuxfcntl() 210*41486Smckusick { 211*41486Smckusick register struct a { 212*41486Smckusick int fdes; 213*41486Smckusick int cmd; 214*41486Smckusick int arg; 215*41486Smckusick } *uap = (struct a *)u.u_ap; 216*41486Smckusick int mode; 217*41486Smckusick 218*41486Smckusick switch (uap->cmd) { 219*41486Smckusick case F_SETFL: 220*41486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 221*41486Smckusick break; 222*41486Smckusick case F_GETFL: 223*41486Smckusick case F_DUPFD: 224*41486Smckusick case F_GETFD: 225*41486Smckusick case F_SETFD: 226*41486Smckusick break; 227*41486Smckusick default: 228*41486Smckusick u.u_error = EINVAL; 229*41486Smckusick return; 230*41486Smckusick } 231*41486Smckusick fcntl(); 232*41486Smckusick if (u.u_error == 0 && uap->arg == F_GETFL) { 233*41486Smckusick mode = u.u_r.r_val1; 234*41486Smckusick u.u_r.r_val1 &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 235*41486Smckusick if (mode & FCREAT) 236*41486Smckusick u.u_r.r_val1 |= HPUXFCREAT; 237*41486Smckusick if (mode & FTRUNC) 238*41486Smckusick u.u_r.r_val1 |= HPUXFTRUNC; 239*41486Smckusick if (mode & FEXCL) 240*41486Smckusick u.u_r.r_val1 |= HPUXFEXCL; 241*41486Smckusick } 242*41486Smckusick } 243*41486Smckusick 244*41486Smckusick /* 245*41486Smckusick * Read and write should return a 0 count when an operation 246*41486Smckusick * on a VNODE would block, not an error. Sockets appear to 247*41486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 248*41486Smckusick * not entirely correct, since the behavior is only defined 249*41486Smckusick * for pipes and tty type devices. 250*41486Smckusick */ 251*41486Smckusick hpuxread() 252*41486Smckusick { 253*41486Smckusick struct a { 254*41486Smckusick int fd; 255*41486Smckusick } *uap = (struct a *)u.u_ap; 256*41486Smckusick 257*41486Smckusick read(); 258*41486Smckusick if (u.u_error == EWOULDBLOCK && 259*41486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 260*41486Smckusick u.u_error = 0; 261*41486Smckusick u.u_r.r_val1 = 0; 262*41486Smckusick } 263*41486Smckusick } 264*41486Smckusick 265*41486Smckusick hpuxwrite() 266*41486Smckusick { 267*41486Smckusick struct a { 268*41486Smckusick int fd; 269*41486Smckusick } *uap = (struct a *)u.u_ap; 270*41486Smckusick 271*41486Smckusick write(); 272*41486Smckusick if (u.u_error == EWOULDBLOCK && 273*41486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 274*41486Smckusick u.u_error = 0; 275*41486Smckusick u.u_r.r_val1 = 0; 276*41486Smckusick } 277*41486Smckusick } 278*41486Smckusick 279*41486Smckusick hpuxreadv() 280*41486Smckusick { 281*41486Smckusick struct a { 282*41486Smckusick int fd; 283*41486Smckusick } *uap = (struct a *)u.u_ap; 284*41486Smckusick 285*41486Smckusick readv(); 286*41486Smckusick if (u.u_error == EWOULDBLOCK && 287*41486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 288*41486Smckusick u.u_error = 0; 289*41486Smckusick u.u_r.r_val1 = 0; 290*41486Smckusick } 291*41486Smckusick } 292*41486Smckusick 293*41486Smckusick hpuxwritev() 294*41486Smckusick { 295*41486Smckusick struct a { 296*41486Smckusick int fd; 297*41486Smckusick } *uap = (struct a *)u.u_ap; 298*41486Smckusick 299*41486Smckusick writev(); 300*41486Smckusick if (u.u_error == EWOULDBLOCK && 301*41486Smckusick u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 302*41486Smckusick u.u_error = 0; 303*41486Smckusick u.u_r.r_val1 = 0; 304*41486Smckusick } 305*41486Smckusick } 306*41486Smckusick 307*41486Smckusick /* 308*41486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 309*41486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 310*41486Smckusick */ 311*41486Smckusick hpuxdup() 312*41486Smckusick { 313*41486Smckusick register struct a { 314*41486Smckusick int i; 315*41486Smckusick } *uap = (struct a *)u.u_ap; 316*41486Smckusick struct file *fp; 317*41486Smckusick int j; 318*41486Smckusick 319*41486Smckusick if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) { 320*41486Smckusick u.u_error = EBADF; 321*41486Smckusick return; 322*41486Smckusick } 323*41486Smckusick u.u_error = ufalloc(0, &j); 324*41486Smckusick if (u.u_error) 325*41486Smckusick return; 326*41486Smckusick u.u_r.r_val1 = j; 327*41486Smckusick dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 328*41486Smckusick } 329*41486Smckusick 330*41486Smckusick hpuxuname() 331*41486Smckusick { 332*41486Smckusick register struct a { 333*41486Smckusick struct hpuxutsname *uts; 334*41486Smckusick int dev; 335*41486Smckusick int request; 336*41486Smckusick } *uap = (struct a *)u.u_ap; 337*41486Smckusick register int i; 338*41486Smckusick 339*41486Smckusick switch (uap->request) { 340*41486Smckusick /* uname */ 341*41486Smckusick case 0: 342*41486Smckusick /* fill in machine type */ 343*41486Smckusick switch (machineid) { 344*41486Smckusick case HP_320: 345*41486Smckusick protoutsname.machine[6] = '2'; 346*41486Smckusick break; 347*41486Smckusick /* includes 318 and 319 */ 348*41486Smckusick case HP_330: 349*41486Smckusick protoutsname.machine[6] = '3'; 350*41486Smckusick break; 351*41486Smckusick case HP_340: 352*41486Smckusick protoutsname.machine[6] = '4'; 353*41486Smckusick break; 354*41486Smckusick case HP_350: 355*41486Smckusick protoutsname.machine[6] = '5'; 356*41486Smckusick break; 357*41486Smckusick case HP_360: 358*41486Smckusick protoutsname.machine[6] = '6'; 359*41486Smckusick break; 360*41486Smckusick case HP_370: 361*41486Smckusick protoutsname.machine[6] = '7'; 362*41486Smckusick break; 363*41486Smckusick } 364*41486Smckusick /* copy hostname (sans domain) to nodename */ 365*41486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 366*41486Smckusick protoutsname.nodename[i] = hostname[i]; 367*41486Smckusick u.u_error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 368*41486Smckusick sizeof(struct hpuxutsname)); 369*41486Smckusick break; 370*41486Smckusick /* ustat - who cares? */ 371*41486Smckusick case 2: 372*41486Smckusick default: 373*41486Smckusick u.u_error = EINVAL; 374*41486Smckusick break; 375*41486Smckusick } 376*41486Smckusick } 377*41486Smckusick 378*41486Smckusick hpuxstat() 379*41486Smckusick { 380*41486Smckusick struct a { 381*41486Smckusick char *fname; 382*41486Smckusick struct hpuxstat *hsb; 383*41486Smckusick } *uap = (struct a *)u.u_ap; 384*41486Smckusick 385*41486Smckusick u.u_error = hpuxstat1(uap->fname, uap->hsb, FOLLOW); 386*41486Smckusick } 387*41486Smckusick 388*41486Smckusick hpuxlstat() 389*41486Smckusick { 390*41486Smckusick struct a { 391*41486Smckusick char *fname; 392*41486Smckusick struct hpuxstat *hsb; 393*41486Smckusick } *uap = (struct a *) u.u_ap; 394*41486Smckusick 395*41486Smckusick u.u_error = hpuxstat1(uap->fname, uap->hsb, NOFOLLOW); 396*41486Smckusick } 397*41486Smckusick 398*41486Smckusick hpuxfstat() 399*41486Smckusick { 400*41486Smckusick register struct file *fp; 401*41486Smckusick register struct a { 402*41486Smckusick int fdes; 403*41486Smckusick struct hpuxstat *hsb; 404*41486Smckusick } *uap = (struct a *)u.u_ap; 405*41486Smckusick struct stat sb; 406*41486Smckusick 407*41486Smckusick if ((unsigned)uap->fdes >= NOFILE || 408*41486Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) { 409*41486Smckusick u.u_error = EBADF; 410*41486Smckusick return; 411*41486Smckusick } 412*41486Smckusick switch (fp->f_type) { 413*41486Smckusick 414*41486Smckusick case DTYPE_VNODE: 415*41486Smckusick u.u_error = vn_stat((struct vnode *)fp->f_data, &sb); 416*41486Smckusick break; 417*41486Smckusick 418*41486Smckusick case DTYPE_SOCKET: 419*41486Smckusick u.u_error = soo_stat((struct socket *)fp->f_data, &sb); 420*41486Smckusick break; 421*41486Smckusick 422*41486Smckusick default: 423*41486Smckusick panic("fstat"); 424*41486Smckusick /*NOTREACHED*/ 425*41486Smckusick } 426*41486Smckusick /* is this right for sockets?? */ 427*41486Smckusick if (u.u_error == 0) 428*41486Smckusick u.u_error = bsdtohpuxstat(&sb, uap->hsb); 429*41486Smckusick } 430*41486Smckusick 431*41486Smckusick hpuxulimit() 432*41486Smckusick { 433*41486Smckusick struct a { 434*41486Smckusick int cmd; 435*41486Smckusick long newlimit; 436*41486Smckusick } *uap = (struct a *)u.u_ap; 437*41486Smckusick struct rlimit *limp; 438*41486Smckusick 439*41486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 440*41486Smckusick switch (uap->cmd) { 441*41486Smckusick case 2: 442*41486Smckusick uap->newlimit *= 512; 443*41486Smckusick if (uap->newlimit > limp->rlim_max && 444*41486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 445*41486Smckusick break; 446*41486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 447*41486Smckusick /* else fall into... */ 448*41486Smckusick 449*41486Smckusick case 1: 450*41486Smckusick u.u_r.r_off = limp->rlim_max / 512; 451*41486Smckusick break; 452*41486Smckusick 453*41486Smckusick case 3: 454*41486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 455*41486Smckusick u.u_r.r_off = ctob(u.u_tsize) + limp->rlim_max; 456*41486Smckusick break; 457*41486Smckusick 458*41486Smckusick default: 459*41486Smckusick u.u_error = EINVAL; 460*41486Smckusick break; 461*41486Smckusick } 462*41486Smckusick } 463*41486Smckusick 464*41486Smckusick /* 465*41486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 466*41486Smckusick * values -16 (high) thru -1 (low). 467*41486Smckusick */ 468*41486Smckusick hpuxrtprio() 469*41486Smckusick { 470*41486Smckusick register struct a { 471*41486Smckusick int pid; 472*41486Smckusick int prio; 473*41486Smckusick } *uap = (struct a *)u.u_ap; 474*41486Smckusick struct proc *p; 475*41486Smckusick int nice; 476*41486Smckusick 477*41486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 478*41486Smckusick uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) { 479*41486Smckusick u.u_error = EINVAL; 480*41486Smckusick return; 481*41486Smckusick } 482*41486Smckusick if (uap->pid == 0) 483*41486Smckusick p = u.u_procp; 484*41486Smckusick else if ((p = pfind(uap->pid)) == 0) { 485*41486Smckusick u.u_error = ESRCH; 486*41486Smckusick return; 487*41486Smckusick } 488*41486Smckusick nice = p->p_nice; 489*41486Smckusick if (nice < NZERO) 490*41486Smckusick u.u_r.r_val1 = (nice + 16) << 3; 491*41486Smckusick else 492*41486Smckusick u.u_r.r_val1 = RTPRIO_RTOFF; 493*41486Smckusick switch (uap->prio) { 494*41486Smckusick 495*41486Smckusick case RTPRIO_NOCHG: 496*41486Smckusick return; 497*41486Smckusick 498*41486Smckusick case RTPRIO_RTOFF: 499*41486Smckusick if (nice >= NZERO) 500*41486Smckusick return; 501*41486Smckusick nice = NZERO; 502*41486Smckusick break; 503*41486Smckusick 504*41486Smckusick default: 505*41486Smckusick nice = (uap->prio >> 3) - 16; 506*41486Smckusick break; 507*41486Smckusick } 508*41486Smckusick donice(p, nice); 509*41486Smckusick if (u.u_error == EACCES) 510*41486Smckusick u.u_error = EPERM; 511*41486Smckusick } 512*41486Smckusick 513*41486Smckusick /* 514*41486Smckusick * Kudos to HP folks for using such mnemonic names so I could figure 515*41486Smckusick * out what this guy does. 516*41486Smckusick */ 517*41486Smckusick hpuxadvise() 518*41486Smckusick { 519*41486Smckusick struct a { 520*41486Smckusick int arg; 521*41486Smckusick } *uap = (struct a *) u.u_ap; 522*41486Smckusick 523*41486Smckusick switch (uap->arg) { 524*41486Smckusick case 0: 525*41486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 526*41486Smckusick break; 527*41486Smckusick case 1: 528*41486Smckusick ICIA(); 529*41486Smckusick break; 530*41486Smckusick case 2: 531*41486Smckusick DCIA(); 532*41486Smckusick break; 533*41486Smckusick default: 534*41486Smckusick u.u_error = EINVAL; 535*41486Smckusick break; 536*41486Smckusick } 537*41486Smckusick } 538*41486Smckusick 539*41486Smckusick hpuxptrace() 540*41486Smckusick { 541*41486Smckusick struct a { 542*41486Smckusick int req; 543*41486Smckusick int pid; 544*41486Smckusick int *addr; 545*41486Smckusick int data; 546*41486Smckusick } *uap = (struct a *)u.u_ap; 547*41486Smckusick 548*41486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 549*41486Smckusick if (uap->data) { 550*41486Smckusick uap->data = hpuxtobsdsig(uap->data); 551*41486Smckusick if (uap->data == 0) 552*41486Smckusick uap->data = NSIG; 553*41486Smckusick } 554*41486Smckusick } 555*41486Smckusick ptrace(); 556*41486Smckusick } 557*41486Smckusick 558*41486Smckusick hpuxgetdomainname() 559*41486Smckusick { 560*41486Smckusick register struct a { 561*41486Smckusick char *domainname; 562*41486Smckusick u_int len; 563*41486Smckusick } *uap = (struct a *)u.u_ap; 564*41486Smckusick 565*41486Smckusick if (uap->len > domainnamelen + 1) 566*41486Smckusick uap->len = domainnamelen + 1; 567*41486Smckusick u.u_error = copyout(domainname, uap->domainname, uap->len); 568*41486Smckusick } 569*41486Smckusick 570*41486Smckusick hpuxsetdomainname() 571*41486Smckusick { 572*41486Smckusick register struct a { 573*41486Smckusick char *domainname; 574*41486Smckusick u_int len; 575*41486Smckusick } *uap = (struct a *)u.u_ap; 576*41486Smckusick 577*41486Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 578*41486Smckusick return; 579*41486Smckusick if (uap->len > sizeof (domainname) - 1) { 580*41486Smckusick u.u_error = EINVAL; 581*41486Smckusick return; 582*41486Smckusick } 583*41486Smckusick domainnamelen = uap->len; 584*41486Smckusick u.u_error = copyin(uap->domainname, domainname, uap->len); 585*41486Smckusick domainname[domainnamelen] = 0; 586*41486Smckusick } 587*41486Smckusick 588*41486Smckusick #ifdef SYSVSHM 589*41486Smckusick hpuxshmat() 590*41486Smckusick { 591*41486Smckusick shmat(u.u_ap); 592*41486Smckusick } 593*41486Smckusick 594*41486Smckusick hpuxshmctl() 595*41486Smckusick { 596*41486Smckusick shmctl(u.u_ap); 597*41486Smckusick } 598*41486Smckusick 599*41486Smckusick hpuxshmdt() 600*41486Smckusick { 601*41486Smckusick shmdt(u.u_ap); 602*41486Smckusick } 603*41486Smckusick 604*41486Smckusick hpuxshmget() 605*41486Smckusick { 606*41486Smckusick shmget(u.u_ap); 607*41486Smckusick } 608*41486Smckusick #endif 609*41486Smckusick 610*41486Smckusick /* 611*41486Smckusick * Fake semaphore routines, just don't return an error. 612*41486Smckusick * Should be adequate for starbase to run. 613*41486Smckusick */ 614*41486Smckusick hpuxsemctl() 615*41486Smckusick { 616*41486Smckusick struct a { 617*41486Smckusick int semid; 618*41486Smckusick u_int semnum; 619*41486Smckusick int cmd; 620*41486Smckusick int arg; 621*41486Smckusick } *uap = (struct a *)u.u_ap; 622*41486Smckusick 623*41486Smckusick /* XXX: should do something here */ 624*41486Smckusick } 625*41486Smckusick 626*41486Smckusick hpuxsemget() 627*41486Smckusick { 628*41486Smckusick struct a { 629*41486Smckusick key_t key; 630*41486Smckusick int nsems; 631*41486Smckusick int semflg; 632*41486Smckusick } *uap = (struct a *)u.u_ap; 633*41486Smckusick 634*41486Smckusick /* XXX: should do something here */ 635*41486Smckusick } 636*41486Smckusick 637*41486Smckusick hpuxsemop() 638*41486Smckusick { 639*41486Smckusick struct a { 640*41486Smckusick int semid; 641*41486Smckusick struct sembuf *sops; 642*41486Smckusick u_int nsops; 643*41486Smckusick } *uap = (struct a *)u.u_ap; 644*41486Smckusick 645*41486Smckusick /* XXX: should do something here */ 646*41486Smckusick } 647*41486Smckusick 648*41486Smckusick /* convert from BSD to HPUX errno */ 649*41486Smckusick bsdtohpuxerrno(err) 650*41486Smckusick int err; 651*41486Smckusick { 652*41486Smckusick if (err < 0 || err >= NERR) 653*41486Smckusick return(BERR); 654*41486Smckusick return((int)bsdtohpuxerrnomap[err]); 655*41486Smckusick } 656*41486Smckusick 657*41486Smckusick hpuxstat1(fname, hsb, follow) 658*41486Smckusick char *fname; 659*41486Smckusick struct hpuxstat *hsb; 660*41486Smckusick int follow; 661*41486Smckusick { 662*41486Smckusick register struct nameidata *ndp = &u.u_nd; 663*41486Smckusick struct stat sb; 664*41486Smckusick int error; 665*41486Smckusick 666*41486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 667*41486Smckusick ndp->ni_segflg = UIO_USERSPACE; 668*41486Smckusick ndp->ni_dirp = fname; 669*41486Smckusick if (error = namei(ndp)) 670*41486Smckusick return (error); 671*41486Smckusick error = vn_stat(ndp->ni_vp, &sb); 672*41486Smckusick vput(ndp->ni_vp); 673*41486Smckusick if (error == 0) 674*41486Smckusick error = bsdtohpuxstat(&sb, hsb); 675*41486Smckusick return (error); 676*41486Smckusick } 677*41486Smckusick 678*41486Smckusick #include "grf.h" 679*41486Smckusick 680*41486Smckusick bsdtohpuxstat(sb, hsb) 681*41486Smckusick struct stat *sb; 682*41486Smckusick struct hpuxstat *hsb; 683*41486Smckusick { 684*41486Smckusick struct hpuxstat ds; 685*41486Smckusick 686*41486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 687*41486Smckusick ds.hst_dev = sb->st_dev; 688*41486Smckusick ds.hst_ino = (u_long)sb->st_ino; 689*41486Smckusick ds.hst_mode = sb->st_mode; 690*41486Smckusick ds.hst_nlink = sb->st_nlink; 691*41486Smckusick ds.hst_uid = (u_short)sb->st_uid; 692*41486Smckusick ds.hst_gid = (u_short)sb->st_gid; 693*41486Smckusick #if NGRF > 0 694*41486Smckusick /* XXX: I don't want to talk about it... */ 695*41486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 696*41486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 697*41486Smckusick else 698*41486Smckusick #endif 699*41486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 700*41486Smckusick ds.hst_size = sb->st_size; 701*41486Smckusick ds.hst_atime = sb->st_atime; 702*41486Smckusick ds.hst_mtime = sb->st_mtime; 703*41486Smckusick ds.hst_ctime = sb->st_ctime; 704*41486Smckusick ds.hst_blksize = sb->st_blksize; 705*41486Smckusick ds.hst_blocks = sb->st_blocks; 706*41486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 707*41486Smckusick } 708*41486Smckusick 709*41486Smckusick hpuxtobsdioctl(com) 710*41486Smckusick int com; 711*41486Smckusick { 712*41486Smckusick switch (com) { 713*41486Smckusick case HPUXTIOCSLTC: 714*41486Smckusick com = TIOCSLTC; break; 715*41486Smckusick case HPUXTIOCGLTC: 716*41486Smckusick com = TIOCGLTC; break; 717*41486Smckusick case HPUXTIOCSPGRP: 718*41486Smckusick com = TIOCSPGRP; break; 719*41486Smckusick case HPUXTIOCGPGRP: 720*41486Smckusick com = TIOCGPGRP; break; 721*41486Smckusick case HPUXTIOCLBIS: 722*41486Smckusick com = TIOCLBIS; break; 723*41486Smckusick case HPUXTIOCLBIC: 724*41486Smckusick com = TIOCLBIC; break; 725*41486Smckusick case HPUXTIOCLSET: 726*41486Smckusick com = TIOCLSET; break; 727*41486Smckusick case HPUXTIOCLGET: 728*41486Smckusick com = TIOCLGET; break; 729*41486Smckusick } 730*41486Smckusick return(com); 731*41486Smckusick } 732*41486Smckusick 733*41486Smckusick /* 734*41486Smckusick * HPUX ioctl system call. The differences here are: 735*41486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 736*41486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 737*41486Smckusick * the sgttyb struct is 2 bytes longer 738*41486Smckusick */ 739*41486Smckusick hpuxioctl() 740*41486Smckusick { 741*41486Smckusick register struct file *fp; 742*41486Smckusick struct a { 743*41486Smckusick int fdes; 744*41486Smckusick int cmd; 745*41486Smckusick caddr_t cmarg; 746*41486Smckusick } *uap = (struct a *)u.u_ap; 747*41486Smckusick register int com; 748*41486Smckusick register u_int size; 749*41486Smckusick caddr_t memp = 0; 750*41486Smckusick #define STK_PARAMS 128 751*41486Smckusick char stkbuf[STK_PARAMS]; 752*41486Smckusick caddr_t data = stkbuf; 753*41486Smckusick 754*41486Smckusick com = uap->cmd; 755*41486Smckusick 756*41486Smckusick /* XXX */ 757*41486Smckusick if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) { 758*41486Smckusick getsettty(uap->fdes, com, uap->cmarg); 759*41486Smckusick return; 760*41486Smckusick } 761*41486Smckusick 762*41486Smckusick if ((unsigned)uap->fdes >= NOFILE || 763*41486Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) { 764*41486Smckusick u.u_error = EBADF; 765*41486Smckusick return; 766*41486Smckusick } 767*41486Smckusick if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 768*41486Smckusick u.u_error = EBADF; 769*41486Smckusick return; 770*41486Smckusick } 771*41486Smckusick 772*41486Smckusick /* 773*41486Smckusick * Interpret high order word to find 774*41486Smckusick * amount of data to be copied to/from the 775*41486Smckusick * user's address space. 776*41486Smckusick */ 777*41486Smckusick size = IOCPARM_LEN(com); 778*41486Smckusick if (size > IOCPARM_MAX) { 779*41486Smckusick u.u_error = EFAULT; 780*41486Smckusick return; 781*41486Smckusick } 782*41486Smckusick if (size > sizeof (stkbuf)) { 783*41486Smckusick memp = (caddr_t)malloc((u_long)IOCPARM_MAX, M_IOCTLOPS, 784*41486Smckusick M_WAITOK); 785*41486Smckusick data = memp; 786*41486Smckusick } 787*41486Smckusick if (com&IOC_IN) { 788*41486Smckusick if (size) { 789*41486Smckusick u.u_error = copyin(uap->cmarg, data, (u_int)size); 790*41486Smckusick if (u.u_error) { 791*41486Smckusick if (memp) 792*41486Smckusick free(memp, M_IOCTLOPS); 793*41486Smckusick return; 794*41486Smckusick } 795*41486Smckusick } else 796*41486Smckusick *(caddr_t *)data = uap->cmarg; 797*41486Smckusick } else if ((com&IOC_OUT) && size) 798*41486Smckusick /* 799*41486Smckusick * Zero the buffer on the stack so the user 800*41486Smckusick * always gets back something deterministic. 801*41486Smckusick */ 802*41486Smckusick bzero(data, size); 803*41486Smckusick else if (com&IOC_VOID) 804*41486Smckusick *(caddr_t *)data = uap->cmarg; 805*41486Smckusick 806*41486Smckusick switch (com) { 807*41486Smckusick 808*41486Smckusick case HPUXTIOCCONS: 809*41486Smckusick *(int *)data = 1; 810*41486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 811*41486Smckusick break; 812*41486Smckusick 813*41486Smckusick /* BSD-style job control ioctls */ 814*41486Smckusick case HPUXTIOCLBIS: 815*41486Smckusick case HPUXTIOCLBIC: 816*41486Smckusick case HPUXTIOCLSET: 817*41486Smckusick *(int *)data &= HPUXLTOSTOP; 818*41486Smckusick if (*(int *)data & HPUXLTOSTOP) 819*41486Smckusick *(int *)data = LTOSTOP; 820*41486Smckusick /* fall into */ 821*41486Smckusick case HPUXTIOCLGET: 822*41486Smckusick case HPUXTIOCSLTC: 823*41486Smckusick case HPUXTIOCGLTC: 824*41486Smckusick case HPUXTIOCSPGRP: 825*41486Smckusick case HPUXTIOCGPGRP: 826*41486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 827*41486Smckusick if (u.u_error == 0 && com == HPUXTIOCLGET) { 828*41486Smckusick *(int *)data &= LTOSTOP; 829*41486Smckusick if (*(int *)data & LTOSTOP) 830*41486Smckusick *(int *)data = HPUXLTOSTOP; 831*41486Smckusick } 832*41486Smckusick break; 833*41486Smckusick 834*41486Smckusick /* SYS 5 termio */ 835*41486Smckusick case HPUXTCGETA: 836*41486Smckusick case HPUXTCSETA: 837*41486Smckusick case HPUXTCSETAW: 838*41486Smckusick case HPUXTCSETAF: 839*41486Smckusick u.u_error = hpuxtermio(fp, com, data); 840*41486Smckusick break; 841*41486Smckusick 842*41486Smckusick default: 843*41486Smckusick u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); 844*41486Smckusick break; 845*41486Smckusick } 846*41486Smckusick /* 847*41486Smckusick * Copy any data to user, size was 848*41486Smckusick * already set and checked above. 849*41486Smckusick */ 850*41486Smckusick if (u.u_error == 0 && (com&IOC_OUT) && size) 851*41486Smckusick u.u_error = copyout(data, uap->cmarg, (u_int)size); 852*41486Smckusick if (memp) 853*41486Smckusick free(memp, M_IOCTLOPS); 854*41486Smckusick } 855*41486Smckusick 856*41486Smckusick /* 857*41486Smckusick * Man page lies, behaviour here is based on observed behaviour. 858*41486Smckusick */ 859*41486Smckusick hpuxgetcontext() 860*41486Smckusick { 861*41486Smckusick struct a { 862*41486Smckusick char *buf; 863*41486Smckusick int len; 864*41486Smckusick } *uap = (struct a *)u.u_ap; 865*41486Smckusick int error = 0; 866*41486Smckusick register int len; 867*41486Smckusick 868*41486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 869*41486Smckusick if (len) 870*41486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 871*41486Smckusick if (!error) 872*41486Smckusick u.u_r.r_val1 = sizeof(hpuxcontext); 873*41486Smckusick return(error); 874*41486Smckusick } 875*41486Smckusick 876*41486Smckusick /* 877*41486Smckusick * XXX: simple recognition hack to see if we can make grmd work. 878*41486Smckusick */ 879*41486Smckusick hpuxlockf() 880*41486Smckusick { 881*41486Smckusick struct a { 882*41486Smckusick int fd; 883*41486Smckusick int func; 884*41486Smckusick long size; 885*41486Smckusick } *uap = (struct a *)u.u_ap; 886*41486Smckusick #ifdef DEBUG 887*41486Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 888*41486Smckusick u.u_procp->p_pid, uap->fd, uap->func, uap->size); 889*41486Smckusick #endif 890*41486Smckusick return(0); 891*41486Smckusick } 892*41486Smckusick 893*41486Smckusick /* 894*41486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 895*41486Smckusick * Note we do not check the real uid or "saved" uid. 896*41486Smckusick */ 897*41486Smckusick hpuxgetpgrp2() 898*41486Smckusick { 899*41486Smckusick register struct proc *p; 900*41486Smckusick register struct a { 901*41486Smckusick int pid; 902*41486Smckusick } *uap = (struct a *)u.u_ap; 903*41486Smckusick 904*41486Smckusick if (uap->pid == 0) 905*41486Smckusick uap->pid = u.u_procp->p_pid; 906*41486Smckusick p = pfind(uap->pid); 907*41486Smckusick if (p == 0) { 908*41486Smckusick u.u_error = ESRCH; 909*41486Smckusick return; 910*41486Smckusick } 911*41486Smckusick if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) { 912*41486Smckusick u.u_error = EPERM; 913*41486Smckusick return; 914*41486Smckusick } 915*41486Smckusick u.u_r.r_val1 = p->p_pgid; 916*41486Smckusick } 917*41486Smckusick 918*41486Smckusick /* 919*41486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 920*41486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 921*41486Smckusick */ 922*41486Smckusick hpuxsetpgrp2() 923*41486Smckusick { 924*41486Smckusick struct a { 925*41486Smckusick int pid; 926*41486Smckusick int pgrp; 927*41486Smckusick } *uap = (struct a *)u.u_ap; 928*41486Smckusick 929*41486Smckusick /* empirically determined */ 930*41486Smckusick if (uap->pgrp < 0 || uap->pgrp >= 30000) { 931*41486Smckusick u.u_error = EINVAL; 932*41486Smckusick return; 933*41486Smckusick } 934*41486Smckusick setpgrp(); 935*41486Smckusick } 936*41486Smckusick 937*41486Smckusick /* 938*41486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 939*41486Smckusick * No apologies offered, if you don't like it, rewrite it! 940*41486Smckusick */ 941*41486Smckusick 942*41486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 943*41486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 944*41486Smckusick 945*41486Smckusick /* simplified FP structure */ 946*41486Smckusick struct bsdfp { 947*41486Smckusick int save[54]; 948*41486Smckusick int reg[24]; 949*41486Smckusick int ctrl[3]; 950*41486Smckusick }; 951*41486Smckusick 952*41486Smckusick hpuxtobsduoff(off) 953*41486Smckusick int *off; 954*41486Smckusick { 955*41486Smckusick struct hpuxfp *hp; 956*41486Smckusick struct bsdfp *bp; 957*41486Smckusick register u_int raddr; 958*41486Smckusick 959*41486Smckusick /* u_ar0 field */ 960*41486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 961*41486Smckusick return(UOFF(u_ar0)); 962*41486Smckusick 963*41486Smckusick #ifdef FPCOPROC 964*41486Smckusick /* 68881 registers from PCB */ 965*41486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 966*41486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 967*41486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 968*41486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 969*41486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 970*41486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 971*41486Smckusick #endif 972*41486Smckusick 973*41486Smckusick /* 974*41486Smckusick * Everything else we recognize comes from the kernel stack, 975*41486Smckusick * so we convert off to an absolute address (if not already) 976*41486Smckusick * for simplicity. 977*41486Smckusick */ 978*41486Smckusick if (off < (int *)ctob(UPAGES)) 979*41486Smckusick off = (int *)((u_int)off + (u_int)&u); 980*41486Smckusick 981*41486Smckusick /* 982*41486Smckusick * 68020 registers. 983*41486Smckusick * We know that the HPUX registers are in the same order as ours. 984*41486Smckusick * The only difference is that their PS is 2 bytes instead of a 985*41486Smckusick * padded 4 like ours throwing the alignment off. 986*41486Smckusick */ 987*41486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 988*41486Smckusick /* 989*41486Smckusick * PS: return low word and high word of PC as HP-UX would 990*41486Smckusick * (e.g. &u.u_ar0[16.5]). 991*41486Smckusick */ 992*41486Smckusick if (off == &u.u_ar0[PS]) 993*41486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 994*41486Smckusick /* 995*41486Smckusick * PC: off will be &u.u_ar0[16.5] 996*41486Smckusick */ 997*41486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 998*41486Smckusick raddr = (u_int) &u.u_ar0[PC]; 999*41486Smckusick /* 1000*41486Smckusick * D0-D7, A0-A7: easy 1001*41486Smckusick */ 1002*41486Smckusick else 1003*41486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 1004*41486Smckusick return((int)(raddr - (u_int)&u)); 1005*41486Smckusick } 1006*41486Smckusick 1007*41486Smckusick /* everything else */ 1008*41486Smckusick return(-1); 1009*41486Smckusick } 1010*41486Smckusick 1011*41486Smckusick /* 1012*41486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 1013*41486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1014*41486Smckusick * convert the entire user struct. 1015*41486Smckusick */ 1016*41486Smckusick hpuxdumpu(vp, cred) 1017*41486Smckusick struct vnode *vp; 1018*41486Smckusick struct ucred *cred; 1019*41486Smckusick { 1020*41486Smckusick int error; 1021*41486Smckusick struct hpuxuser *faku; 1022*41486Smckusick struct bsdfp *bp; 1023*41486Smckusick short *foop; 1024*41486Smckusick 1025*41486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1026*41486Smckusick /* 1027*41486Smckusick * Make sure there is no mistake about this 1028*41486Smckusick * being a real user structure. 1029*41486Smckusick */ 1030*41486Smckusick bzero((caddr_t)faku, ctob(1)); 1031*41486Smckusick /* 1032*41486Smckusick * Fill in the process sizes. 1033*41486Smckusick */ 1034*41486Smckusick faku->hpuxu_tsize = u.u_tsize; 1035*41486Smckusick faku->hpuxu_dsize = u.u_dsize; 1036*41486Smckusick faku->hpuxu_ssize = u.u_ssize; 1037*41486Smckusick /* 1038*41486Smckusick * Fill in the exec header for CDB. 1039*41486Smckusick * This was saved back in exec(). As far as I can tell CDB 1040*41486Smckusick * only uses this information to verify that a particular 1041*41486Smckusick * core file goes with a particular binary. 1042*41486Smckusick */ 1043*41486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 1044*41486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1045*41486Smckusick /* 1046*41486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 1047*41486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 1048*41486Smckusick * so we have to move it up. 1049*41486Smckusick */ 1050*41486Smckusick faku->hpuxu_ar0 = u.u_ar0; 1051*41486Smckusick foop = (short *) u.u_ar0; 1052*41486Smckusick foop[32] = foop[33]; 1053*41486Smckusick foop[33] = foop[34]; 1054*41486Smckusick foop[34] = foop[35]; 1055*41486Smckusick #ifdef FPCOPROC 1056*41486Smckusick /* 1057*41486Smckusick * Copy 68881 registers from our PCB format to HPUX format 1058*41486Smckusick */ 1059*41486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 1060*41486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1061*41486Smckusick sizeof(bp->save)); 1062*41486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1063*41486Smckusick sizeof(bp->ctrl)); 1064*41486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1065*41486Smckusick sizeof(bp->reg)); 1066*41486Smckusick #endif 1067*41486Smckusick /* 1068*41486Smckusick * Slay the dragon 1069*41486Smckusick */ 1070*41486Smckusick faku->hpuxu_dragon = -1; 1071*41486Smckusick /* 1072*41486Smckusick * Dump this artfully constructed page in place of the 1073*41486Smckusick * user struct page. 1074*41486Smckusick */ 1075*41486Smckusick error = vn_rdwr(UIO_WRITE, vp, 1076*41486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 1077*41486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 1078*41486Smckusick /* 1079*41486Smckusick * Dump the remaining UPAGES-1 pages normally 1080*41486Smckusick */ 1081*41486Smckusick if (!error) 1082*41486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 1083*41486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1084*41486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 1085*41486Smckusick free((caddr_t)faku, M_TEMP); 1086*41486Smckusick return(error); 1087*41486Smckusick } 1088*41486Smckusick 1089*41486Smckusick /* 1090*41486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 1091*41486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1092*41486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1093*41486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 1094*41486Smckusick */ 1095*41486Smckusick /* #ifdef COMPAT */ 1096*41486Smckusick 1097*41486Smckusick #include "../h/times.h" 1098*41486Smckusick 1099*41486Smckusick /* from old timeb.h */ 1100*41486Smckusick struct hpuxtimeb { 1101*41486Smckusick time_t time; 1102*41486Smckusick u_short millitm; 1103*41486Smckusick short timezone; 1104*41486Smckusick short dstflag; 1105*41486Smckusick }; 1106*41486Smckusick 1107*41486Smckusick /* ye ole stat structure */ 1108*41486Smckusick struct ohpuxstat { 1109*41486Smckusick dev_t ohst_dev; 1110*41486Smckusick u_short ohst_ino; 1111*41486Smckusick u_short ohst_mode; 1112*41486Smckusick short ohst_nlink; 1113*41486Smckusick short ohst_uid; 1114*41486Smckusick short ohst_gid; 1115*41486Smckusick dev_t ohst_rdev; 1116*41486Smckusick int ohst_size; 1117*41486Smckusick int ohst_atime; 1118*41486Smckusick int ohst_mtime; 1119*41486Smckusick int ohst_ctime; 1120*41486Smckusick }; 1121*41486Smckusick 1122*41486Smckusick /* 1123*41486Smckusick * Right now the following two routines are the same as the 4.3 1124*41486Smckusick * osetuid/osetgid calls. Eventually they need to be changed to 1125*41486Smckusick * implement the notion of "saved" ids (whatever that means). 1126*41486Smckusick */ 1127*41486Smckusick ohpuxsetuid() 1128*41486Smckusick { 1129*41486Smckusick register uid; 1130*41486Smckusick register struct a { 1131*41486Smckusick int uid; 1132*41486Smckusick } *uap = (struct a *)u.u_ap; 1133*41486Smckusick 1134*41486Smckusick uid = uap->uid; 1135*41486Smckusick if (uid != u.u_procp->p_ruid && uid != u.u_cred->cr_uid && 1136*41486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1137*41486Smckusick return; 1138*41486Smckusick if (u.u_cred->cr_ref > 1) 1139*41486Smckusick u.u_cred = crcopy(u.u_cred); 1140*41486Smckusick u.u_cred->cr_uid = uid; 1141*41486Smckusick u.u_procp->p_uid = uid; 1142*41486Smckusick u.u_procp->p_ruid = uid; 1143*41486Smckusick } 1144*41486Smckusick 1145*41486Smckusick ohpuxsetgid() 1146*41486Smckusick { 1147*41486Smckusick register gid; 1148*41486Smckusick register struct a { 1149*41486Smckusick int gid; 1150*41486Smckusick } *uap = (struct a *)u.u_ap; 1151*41486Smckusick 1152*41486Smckusick gid = uap->gid; 1153*41486Smckusick if (u.u_procp->p_rgid != gid && u.u_cred->cr_groups[0] != gid && 1154*41486Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1155*41486Smckusick return; 1156*41486Smckusick if (u.u_cred->cr_ref > 1) 1157*41486Smckusick u.u_cred = crcopy(u.u_cred); 1158*41486Smckusick u.u_procp->p_rgid = gid; 1159*41486Smckusick u.u_cred->cr_groups[0] = gid; 1160*41486Smckusick } 1161*41486Smckusick 1162*41486Smckusick /* 1163*41486Smckusick * SYS V style setpgrp() 1164*41486Smckusick */ 1165*41486Smckusick ohpuxsetpgrp() 1166*41486Smckusick { 1167*41486Smckusick register struct proc *p = u.u_procp; 1168*41486Smckusick 1169*41486Smckusick if (p->p_pid != p->p_pgid) 1170*41486Smckusick pgmv(p, p->p_pid, 0); 1171*41486Smckusick u.u_r.r_val1 = p->p_pgid; 1172*41486Smckusick } 1173*41486Smckusick 1174*41486Smckusick ohpuxtime() 1175*41486Smckusick { 1176*41486Smckusick register struct a { 1177*41486Smckusick long *tp; 1178*41486Smckusick } *uap = (struct a *)u.u_ap; 1179*41486Smckusick 1180*41486Smckusick if (uap->tp) 1181*41486Smckusick u.u_error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1182*41486Smckusick sizeof (long)); 1183*41486Smckusick u.u_r.r_time = time.tv_sec; 1184*41486Smckusick } 1185*41486Smckusick 1186*41486Smckusick ohpuxstime() 1187*41486Smckusick { 1188*41486Smckusick register struct a { 1189*41486Smckusick int time; 1190*41486Smckusick } *uap = (struct a *)u.u_ap; 1191*41486Smckusick struct timeval tv; 1192*41486Smckusick int s; 1193*41486Smckusick 1194*41486Smckusick tv.tv_sec = uap->time; 1195*41486Smckusick tv.tv_usec = 0; 1196*41486Smckusick u.u_error = suser(u.u_cred, &u.u_acflag); 1197*41486Smckusick if (u.u_error) 1198*41486Smckusick return; 1199*41486Smckusick 1200*41486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1201*41486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 1202*41486Smckusick s = splhigh(); time = tv; splx(s); 1203*41486Smckusick resettodr(); 1204*41486Smckusick } 1205*41486Smckusick 1206*41486Smckusick ohpuxftime() 1207*41486Smckusick { 1208*41486Smckusick register struct a { 1209*41486Smckusick struct hpuxtimeb *tp; 1210*41486Smckusick } *uap; 1211*41486Smckusick struct hpuxtimeb tb; 1212*41486Smckusick int s; 1213*41486Smckusick 1214*41486Smckusick uap = (struct a *)u.u_ap; 1215*41486Smckusick s = splhigh(); 1216*41486Smckusick tb.time = time.tv_sec; 1217*41486Smckusick tb.millitm = time.tv_usec / 1000; 1218*41486Smckusick splx(s); 1219*41486Smckusick tb.timezone = tz.tz_minuteswest; 1220*41486Smckusick tb.dstflag = tz.tz_dsttime; 1221*41486Smckusick u.u_error = copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)); 1222*41486Smckusick } 1223*41486Smckusick 1224*41486Smckusick ohpuxalarm() 1225*41486Smckusick { 1226*41486Smckusick register struct a { 1227*41486Smckusick int deltat; 1228*41486Smckusick } *uap = (struct a *)u.u_ap; 1229*41486Smckusick register struct proc *p = u.u_procp; 1230*41486Smckusick int s = splhigh(); 1231*41486Smckusick 1232*41486Smckusick untimeout(realitexpire, (caddr_t)p); 1233*41486Smckusick timerclear(&p->p_realtimer.it_interval); 1234*41486Smckusick u.u_r.r_val1 = 0; 1235*41486Smckusick if (timerisset(&p->p_realtimer.it_value) && 1236*41486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 1237*41486Smckusick u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1238*41486Smckusick if (uap->deltat == 0) { 1239*41486Smckusick timerclear(&p->p_realtimer.it_value); 1240*41486Smckusick splx(s); 1241*41486Smckusick return; 1242*41486Smckusick } 1243*41486Smckusick p->p_realtimer.it_value = time; 1244*41486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 1245*41486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1246*41486Smckusick splx(s); 1247*41486Smckusick } 1248*41486Smckusick 1249*41486Smckusick ohpuxnice() 1250*41486Smckusick { 1251*41486Smckusick register struct a { 1252*41486Smckusick int niceness; 1253*41486Smckusick } *uap = (struct a *)u.u_ap; 1254*41486Smckusick register struct proc *p = u.u_procp; 1255*41486Smckusick 1256*41486Smckusick donice(p, (p->p_nice-NZERO)+uap->niceness); 1257*41486Smckusick u.u_r.r_val1 = p->p_nice - NZERO; 1258*41486Smckusick } 1259*41486Smckusick 1260*41486Smckusick ohpuxtimes() 1261*41486Smckusick { 1262*41486Smckusick register struct a { 1263*41486Smckusick struct tms *tmsb; 1264*41486Smckusick } *uap = (struct a *)u.u_ap; 1265*41486Smckusick struct tms atms; 1266*41486Smckusick 1267*41486Smckusick atms.tms_utime = scale50(&u.u_ru.ru_utime); 1268*41486Smckusick atms.tms_stime = scale50(&u.u_ru.ru_stime); 1269*41486Smckusick atms.tms_cutime = scale50(&u.u_cru.ru_utime); 1270*41486Smckusick atms.tms_cstime = scale50(&u.u_cru.ru_stime); 1271*41486Smckusick u.u_error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1272*41486Smckusick if (u.u_error == 0) 1273*41486Smckusick u.u_r.r_time = scale50(&time) - scale50(&boottime); 1274*41486Smckusick } 1275*41486Smckusick 1276*41486Smckusick scale50(tvp) 1277*41486Smckusick register struct timeval *tvp; 1278*41486Smckusick { 1279*41486Smckusick extern int hpuxtick; 1280*41486Smckusick 1281*41486Smckusick /* 1282*41486Smckusick * Doesn't exactly do what the documentation says. 1283*41486Smckusick * What we really do is return 50th of a second since that 1284*41486Smckusick * is what HZ is on all bobcats I know of. 1285*41486Smckusick */ 1286*41486Smckusick return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick)); 1287*41486Smckusick } 1288*41486Smckusick 1289*41486Smckusick /* 1290*41486Smckusick * Set IUPD and IACC times on file. 1291*41486Smckusick * Can't set ICHG. 1292*41486Smckusick */ 1293*41486Smckusick ohpuxutime() 1294*41486Smckusick { 1295*41486Smckusick register struct a { 1296*41486Smckusick char *fname; 1297*41486Smckusick time_t *tptr; 1298*41486Smckusick } *uap = (struct a *)u.u_ap; 1299*41486Smckusick struct vattr vattr; 1300*41486Smckusick time_t tv[2]; 1301*41486Smckusick register struct vnode *vp; 1302*41486Smckusick register struct nameidata *ndp = &u.u_nd; 1303*41486Smckusick 1304*41486Smckusick if (uap->tptr) { 1305*41486Smckusick u.u_error = 1306*41486Smckusick copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1307*41486Smckusick if (u.u_error) 1308*41486Smckusick return; 1309*41486Smckusick } else 1310*41486Smckusick tv[0] = tv[1] = time.tv_sec; 1311*41486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1312*41486Smckusick ndp->ni_segflg = UIO_USERSPACE; 1313*41486Smckusick ndp->ni_dirp = uap->fname; 1314*41486Smckusick vattr_null(&vattr); 1315*41486Smckusick vattr.va_atime.tv_sec = tv[0]; 1316*41486Smckusick vattr.va_atime.tv_usec = 0; 1317*41486Smckusick vattr.va_mtime.tv_sec = tv[1]; 1318*41486Smckusick vattr.va_mtime.tv_usec = 0; 1319*41486Smckusick if (u.u_error = namei(ndp)) 1320*41486Smckusick return; 1321*41486Smckusick vp = ndp->ni_vp; 1322*41486Smckusick if (vp->v_mount->m_flag & M_RDONLY) 1323*41486Smckusick u.u_error = EROFS; 1324*41486Smckusick else 1325*41486Smckusick u.u_error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 1326*41486Smckusick vput(vp); 1327*41486Smckusick } 1328*41486Smckusick 1329*41486Smckusick ohpuxpause() 1330*41486Smckusick { 1331*41486Smckusick 1332*41486Smckusick for (;;) 1333*41486Smckusick sleep((caddr_t)&u, PSLEP); 1334*41486Smckusick } 1335*41486Smckusick 1336*41486Smckusick /* 1337*41486Smckusick * The old fstat system call. 1338*41486Smckusick */ 1339*41486Smckusick ohpuxfstat() 1340*41486Smckusick { 1341*41486Smckusick register struct a { 1342*41486Smckusick int fd; 1343*41486Smckusick struct ohpuxstat *sb; 1344*41486Smckusick } *uap = (struct a *)u.u_ap; 1345*41486Smckusick struct file *fp; 1346*41486Smckusick extern struct file *getinode(); 1347*41486Smckusick 1348*41486Smckusick if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) { 1349*41486Smckusick u.u_error = EBADF; 1350*41486Smckusick return; 1351*41486Smckusick } 1352*41486Smckusick if (fp->f_type != DTYPE_VNODE) { 1353*41486Smckusick u.u_error = EINVAL; 1354*41486Smckusick return; 1355*41486Smckusick } 1356*41486Smckusick u.u_error = ohpuxstat1((struct vnode *)fp->f_data, uap->sb); 1357*41486Smckusick } 1358*41486Smckusick 1359*41486Smckusick /* 1360*41486Smckusick * Old stat system call. This version follows links. 1361*41486Smckusick */ 1362*41486Smckusick ohpuxstat() 1363*41486Smckusick { 1364*41486Smckusick register struct a { 1365*41486Smckusick char *fname; 1366*41486Smckusick struct ohpuxstat *sb; 1367*41486Smckusick } *uap = (struct a *)u.u_ap; 1368*41486Smckusick register struct nameidata *ndp = &u.u_nd; 1369*41486Smckusick 1370*41486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 1371*41486Smckusick ndp->ni_segflg = UIO_USERSPACE; 1372*41486Smckusick ndp->ni_dirp = uap->fname; 1373*41486Smckusick if (u.u_error = namei(ndp)) 1374*41486Smckusick return; 1375*41486Smckusick u.u_error = ohpuxstat1(ndp->ni_vp, uap->sb); 1376*41486Smckusick vput(ndp->ni_vp); 1377*41486Smckusick } 1378*41486Smckusick 1379*41486Smckusick int 1380*41486Smckusick ohpuxstat1(vp, ub) 1381*41486Smckusick register struct vnode *vp; 1382*41486Smckusick struct ohpuxstat *ub; 1383*41486Smckusick { 1384*41486Smckusick struct ohpuxstat ds; 1385*41486Smckusick struct vattr vattr; 1386*41486Smckusick register int error; 1387*41486Smckusick 1388*41486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 1389*41486Smckusick if (error) 1390*41486Smckusick return(error); 1391*41486Smckusick /* 1392*41486Smckusick * Copy from inode table 1393*41486Smckusick */ 1394*41486Smckusick ds.ohst_dev = vattr.va_fsid; 1395*41486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 1396*41486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 1397*41486Smckusick ds.ohst_nlink = vattr.va_nlink; 1398*41486Smckusick ds.ohst_uid = (short)vattr.va_uid; 1399*41486Smckusick ds.ohst_gid = (short)vattr.va_gid; 1400*41486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 1401*41486Smckusick ds.ohst_size = (int)vattr.va_size; 1402*41486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 1403*41486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 1404*41486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 1405*41486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1406*41486Smckusick } 1407*41486Smckusick /* #endif */ 1408*41486Smckusick 1409*41486Smckusick #endif 1410