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