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 * 12*57307Shibler * from: Utah $Hdr: hpux_compat.c 1.55 92/12/26$ 1341486Smckusick * 14*57307Shibler * @(#)hpux_compat.c 7.33 (Berkeley) 12/27/92 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1854857Shibler * Various HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2356506Sbostic #include <sys/param.h> 2456506Sbostic #include <sys/systm.h> 2556506Sbostic #include <sys/signalvar.h> 2656506Sbostic #include <sys/kernel.h> 2756506Sbostic #include <sys/filedesc.h> 2856506Sbostic #include <sys/proc.h> 2956506Sbostic #include <sys/buf.h> 3056506Sbostic #include <sys/wait.h> 3156506Sbostic #include <sys/file.h> 3256506Sbostic #include <sys/namei.h> 3356506Sbostic #include <sys/vnode.h> 3456506Sbostic #include <sys/ioctl.h> 3556506Sbostic #include <sys/ptrace.h> 3656506Sbostic #include <sys/stat.h> 3756506Sbostic #include <sys/syslog.h> 3856506Sbostic #include <sys/malloc.h> 3956506Sbostic #include <sys/mount.h> 4056506Sbostic #include <sys/ipc.h> 4156506Sbostic #include <sys/user.h> 42*57307Shibler #include <sys/mman.h> 4341486Smckusick 4456506Sbostic #include <machine/cpu.h> 4556506Sbostic #include <machine/reg.h> 4656506Sbostic #include <machine/psl.h> 4756506Sbostic #include <machine/vmparam.h> 4856506Sbostic #include <hp/hpux/hpux.h> 4956506Sbostic #include <hp/hpux/hpux_termio.h> 5056506Sbostic 5141486Smckusick #ifdef DEBUG 5241486Smckusick int unimpresponse = 0; 5341486Smckusick #endif 5441486Smckusick 5541486Smckusick /* SYS5 style UTSNAME info */ 5641486Smckusick struct hpuxutsname protoutsname = { 57*57307Shibler "4.4bsd", "", "0.5", "B", "9000/3?0", "" 5841486Smckusick }; 5941486Smckusick 6041486Smckusick /* 6.0 and later style context */ 6153922Shibler #if defined(HP380) 6253922Shibler char hpux040context[] = 6353922Shibler "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6453922Shibler #endif 6541486Smckusick #ifdef FPCOPROC 6641486Smckusick char hpuxcontext[] = 6741486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6841486Smckusick #else 6941486Smckusick char hpuxcontext[] = 7041486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 7141486Smckusick #endif 7241486Smckusick 7341486Smckusick /* YP domainname */ 7441486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7541486Smckusick int domainnamelen = 7; 7641486Smckusick 7741486Smckusick #define NERR 79 7841486Smckusick #define BERR 1000 7941486Smckusick 8041486Smckusick /* indexed by BSD errno */ 8141486Smckusick short bsdtohpuxerrnomap[NERR] = { 8241486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8341486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8441486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8541486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8641486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8741486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8841486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8941486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 9041486Smckusick }; 9141486Smckusick 9243452Shibler notimp(p, uap, retval, code, nargs) 9343452Shibler struct proc *p; 9443452Shibler int *uap, *retval; 9543452Shibler int code, nargs; 9641486Smckusick { 9743452Shibler int error = 0; 9841486Smckusick #ifdef DEBUG 9943452Shibler register int *argp = uap; 10041486Smckusick extern char *hpuxsyscallnames[]; 10141486Smckusick 10254857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10341486Smckusick if (nargs) 10441486Smckusick while (nargs--) 10541486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10641486Smckusick else 10741486Smckusick printf(")"); 10841486Smckusick printf("\n"); 10941486Smckusick switch (unimpresponse) { 11041486Smckusick case 0: 11143452Shibler error = nosys(p, uap, retval); 11241486Smckusick break; 11341486Smckusick case 1: 11443452Shibler error = EINVAL; 11541486Smckusick break; 11641486Smckusick } 11741486Smckusick #else 11843452Shibler error = nosys(p, uap, retval); 11941486Smckusick #endif 12043452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12144421Skarels return (error); 12241486Smckusick } 12341486Smckusick 12454917Storek struct hpuxexecv_args { 12554917Storek char *fname; 12654917Storek char **argp; 12754917Storek char **envp; 12854917Storek }; 12948478Skarels hpuxexecv(p, uap, retval) 13048478Skarels struct proc *p; 13154917Storek struct hpuxexecv_args *uap; 13248478Skarels int *retval; 13348478Skarels { 13448478Skarels extern int execve(); 13548478Skarels 13648478Skarels uap->envp = NULL; 13748478Skarels return (execve(p, uap, retval)); 13848478Skarels } 13948478Skarels 14041486Smckusick /* 14154857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 14241486Smckusick * (status pointer, options, rusage) into the kernel rather than 14342352Smckusick * handling it in the C library stub. We also need to map any 14454857Shibler * termination signal from BSD to HP-UX. 14541486Smckusick */ 14654917Storek struct hpuxwait3_args { 14754917Storek int *status; 14854917Storek int options; 14954917Storek int rusage; 15054917Storek }; 15143452Shibler hpuxwait3(p, uap, retval) 15243452Shibler struct proc *p; 15354917Storek struct hpuxwait3_args *uap; 15443452Shibler int *retval; 15543452Shibler { 15641486Smckusick /* rusage pointer must be zero */ 15743452Shibler if (uap->rusage) 15844421Skarels return (EINVAL); 15952381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 16052381Smckusick p->p_md.md_regs[R0] = uap->options; 16152381Smckusick p->p_md.md_regs[R1] = uap->rusage; 16244421Skarels return (hpuxwait(p, uap, retval)); 16341486Smckusick } 16441486Smckusick 16554917Storek struct hpuxwait_args { 16654917Storek int *status; 16754917Storek }; 16843452Shibler hpuxwait(p, uap, retval) 16943452Shibler struct proc *p; 17054917Storek struct hpuxwait_args *uap; 17143452Shibler int *retval; 17241486Smckusick { 17343452Shibler int sig, *statp, error; 17441486Smckusick 17541486Smckusick statp = uap->status; /* owait clobbers first arg */ 17643452Shibler error = owait(p, uap, retval); 17741486Smckusick /* 17841486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 17941486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 18041486Smckusick */ 18143452Shibler if (error == ERESTART) 18243452Shibler error = EINTR; 18343452Shibler if (error) 18444421Skarels return (error); 18543452Shibler sig = retval[1] & 0xFF; 18641486Smckusick if (sig == WSTOPPED) { 18743452Shibler sig = (retval[1] >> 8) & 0xFF; 18843452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 18941486Smckusick } else if (sig) 19043452Shibler retval[1] = (retval[1] & 0xFF00) | 19141486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 19241486Smckusick if (statp) 19343452Shibler if (suword((caddr_t)statp, retval[1])) 19443452Shibler error = EFAULT; 19544421Skarels return (error); 19641486Smckusick } 19741486Smckusick 19854917Storek struct hpuxwaitpid_args { 19954917Storek int pid; 20054917Storek int *status; 20154917Storek int options; 20254917Storek struct rusage *rusage; /* wait4 arg */ 20354917Storek }; 20443452Shibler hpuxwaitpid(p, uap, retval) 20543452Shibler struct proc *p; 20654917Storek struct hpuxwaitpid_args *uap; 20743452Shibler int *retval; 20843452Shibler { 20955832Shibler int rv, sig, xstat, error; 21042352Smckusick 21142352Smckusick uap->rusage = 0; 21243452Shibler error = wait4(p, uap, retval); 21342352Smckusick /* 21442352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21542352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21642352Smckusick */ 21743452Shibler if (error == ERESTART) 21843452Shibler error = EINTR; 21943452Shibler if (error) 22044421Skarels return (error); 22155832Shibler if (uap->status) { 22255832Shibler /* 22355832Shibler * Wait4 already wrote the status out to user space, 22455832Shibler * pull it back, change the signal portion, and write 22555832Shibler * it back out. 22655832Shibler */ 22755832Shibler rv = fuword((caddr_t)uap->status); 22855832Shibler if (WIFSTOPPED(rv)) { 22955832Shibler sig = WSTOPSIG(rv); 23055832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 23155832Shibler } else if (WIFSIGNALED(rv)) { 23255832Shibler sig = WTERMSIG(rv); 23355832Shibler xstat = WEXITSTATUS(rv); 23455832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 23555832Shibler WCOREDUMP(rv); 23655832Shibler } 23755832Shibler (void)suword((caddr_t)uap->status, rv); 23855832Shibler } 23944421Skarels return (error); 24042352Smckusick } 24142352Smckusick 24241486Smckusick /* 24341486Smckusick * Must remap some bits in the mode mask. 24441486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 24541486Smckusick * O_SYNCIO (0100000) is removed entirely. 24641486Smckusick */ 24754917Storek struct hpuxopen_args { 24854917Storek char *fname; 24954917Storek int mode; 25054917Storek int crtmode; 25154917Storek }; 25243067Skarels hpuxopen(p, uap, retval) 25343067Skarels struct proc *p; 25454917Storek register struct hpuxopen_args *uap; 25543067Skarels int *retval; 25643067Skarels { 25741486Smckusick int mode; 25841486Smckusick 25941486Smckusick mode = uap->mode; 26041486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 26141486Smckusick if (mode & HPUXFCREAT) { 26241486Smckusick /* 26341486Smckusick * simulate the pre-NFS behavior that opening a 26441486Smckusick * file for READ+CREATE ignores the CREATE (unless 26541486Smckusick * EXCL is set in which case we will return the 26641486Smckusick * proper error). 26741486Smckusick */ 26848478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 26949950Smckusick uap->mode |= O_CREAT; 27041486Smckusick } 27141486Smckusick if (mode & HPUXFTRUNC) 27249950Smckusick uap->mode |= O_TRUNC; 27341486Smckusick if (mode & HPUXFEXCL) 27449950Smckusick uap->mode |= O_EXCL; 27544421Skarels return (open(p, uap, retval)); 27641486Smckusick } 27741486Smckusick 27855832Shibler /* 27955832Shibler * Old creat system call. 28055832Shibler */ 28155832Shibler struct hpuxcreat_args { 28255832Shibler char *fname; 28355832Shibler int fmode; 28455832Shibler }; 28555832Shibler hpuxcreat(p, uap, retval) 28655832Shibler struct proc *p; 28755832Shibler register struct hpuxcreat_args *uap; 28855832Shibler int *retval; 28955832Shibler { 29055832Shibler struct nargs { 29155832Shibler char *fname; 29255832Shibler int mode; 29355832Shibler int crtmode; 29455832Shibler } openuap; 29555832Shibler 29655832Shibler openuap.fname = uap->fname; 29755832Shibler openuap.crtmode = uap->fmode; 29855832Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 29955832Shibler return (open(p, &openuap, retval)); 30055832Shibler } 30155832Shibler 30249329Shibler /* XXX */ 30349329Shibler #define UF_FNDELAY_ON 0x20 30449329Shibler #define UF_FIONBIO_ON 0x40 30549329Shibler /* XXX */ 30649329Shibler 30754917Storek struct hpuxfcntl_args { 30854917Storek int fdes; 30954917Storek int cmd; 31054917Storek int arg; 31154917Storek }; 31243452Shibler hpuxfcntl(p, uap, retval) 31343452Shibler struct proc *p; 31454917Storek register struct hpuxfcntl_args *uap; 31543452Shibler int *retval; 31643452Shibler { 31743452Shibler int mode, error; 31849329Shibler char *fp; 31941486Smckusick 32049329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 32149329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 32249329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 32349329Shibler return (EBADF); 32449329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 32549329Shibler } 32641486Smckusick switch (uap->cmd) { 32741486Smckusick case F_SETFL: 32849950Smckusick if (uap->arg & FNONBLOCK) 32949329Shibler *fp |= UF_FNDELAY_ON; 33049329Shibler else { 33149329Shibler *fp &= ~UF_FNDELAY_ON; 33249329Shibler if (*fp & UF_FIONBIO_ON) 33349950Smckusick uap->arg |= FNONBLOCK; 33449329Shibler } 33541486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 33641486Smckusick break; 33741486Smckusick case F_GETFL: 33841486Smckusick case F_DUPFD: 33941486Smckusick case F_GETFD: 34041486Smckusick case F_SETFD: 34141486Smckusick break; 34241486Smckusick default: 34344421Skarels return (EINVAL); 34441486Smckusick } 34543452Shibler error = fcntl(p, uap, retval); 34649329Shibler if (error == 0 && uap->cmd == F_GETFL) { 34743452Shibler mode = *retval; 34849950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 34949950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 35049950Smckusick *retval &= ~FNONBLOCK; 35149950Smckusick if (mode & O_CREAT) 35243452Shibler *retval |= HPUXFCREAT; 35349950Smckusick if (mode & O_TRUNC) 35443452Shibler *retval |= HPUXFTRUNC; 35549950Smckusick if (mode & O_EXCL) 35643452Shibler *retval |= HPUXFEXCL; 35741486Smckusick } 35844421Skarels return (error); 35941486Smckusick } 36041486Smckusick 36141486Smckusick /* 36241486Smckusick * Read and write should return a 0 count when an operation 36349329Shibler * on a VNODE would block, not an error. 36449329Shibler * 36549329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 36649950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 36741486Smckusick */ 36854917Storek struct hpuxread_args { 36954917Storek int fd; 37054917Storek }; 37143452Shibler hpuxread(p, uap, retval) 37243452Shibler struct proc *p; 37354917Storek struct hpuxread_args *uap; 37443452Shibler int *retval; 37541486Smckusick { 37643452Shibler int error; 37741486Smckusick 37843452Shibler error = read(p, uap, retval); 37943452Shibler if (error == EWOULDBLOCK && 38049329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 38149329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 38243452Shibler error = 0; 38343452Shibler *retval = 0; 38441486Smckusick } 38544421Skarels return (error); 38641486Smckusick } 38741486Smckusick 38854917Storek struct hpuxwrite_args { 38954917Storek int fd; 39054917Storek }; 39143452Shibler hpuxwrite(p, uap, retval) 39243452Shibler struct proc *p; 39354917Storek struct hpuxwrite_args *uap; 39443452Shibler int *retval; 39541486Smckusick { 39643452Shibler int error; 39741486Smckusick 39843452Shibler error = write(p, uap, retval); 39943452Shibler if (error == EWOULDBLOCK && 40049329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 40149329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 40243452Shibler error = 0; 40343452Shibler *retval = 0; 40441486Smckusick } 40544421Skarels return (error); 40641486Smckusick } 40741486Smckusick 40854917Storek struct hpuxreadv_args { 40954917Storek int fd; 41054917Storek }; 41143452Shibler hpuxreadv(p, uap, retval) 41243452Shibler struct proc *p; 41354917Storek struct hpuxreadv_args *uap; 41443452Shibler int *retval; 41541486Smckusick { 41643452Shibler int error; 41741486Smckusick 41843452Shibler error = readv(p, uap, retval); 41943452Shibler if (error == EWOULDBLOCK && 42049329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 42149329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 42243452Shibler error = 0; 42343452Shibler *retval = 0; 42441486Smckusick } 42544421Skarels return (error); 42641486Smckusick } 42741486Smckusick 42854917Storek struct hpuxwritev_args { 42954917Storek int fd; 43054917Storek }; 43143452Shibler hpuxwritev(p, uap, retval) 43243452Shibler struct proc *p; 43354917Storek struct hpuxwritev_args *uap; 43443452Shibler int *retval; 43541486Smckusick { 43643452Shibler int error; 43741486Smckusick 43843452Shibler error = writev(p, uap, retval); 43943452Shibler if (error == EWOULDBLOCK && 44049329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 44149329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 44243452Shibler error = 0; 44343452Shibler *retval = 0; 44441486Smckusick } 44544421Skarels return (error); 44641486Smckusick } 44741486Smckusick 44841486Smckusick /* 44941486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 45054857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 45141486Smckusick */ 45254917Storek struct hpuxdup_args { 45354917Storek int i; 45454917Storek }; 45543452Shibler hpuxdup(p, uap, retval) 45643452Shibler struct proc *p; 45754917Storek register struct hpuxdup_args *uap; 45843452Shibler int *retval; 45941486Smckusick { 46045923Smckusick register struct filedesc *fdp = p->p_fd; 46141486Smckusick struct file *fp; 46243452Shibler int fd, error; 46341486Smckusick 46448478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 46548478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 46644421Skarels return (EBADF); 46748478Skarels if (error = fdalloc(p, 0, &fd)) 46844421Skarels return (error); 46948478Skarels fdp->fd_ofiles[fd] = fp; 47048478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 47145923Smckusick fp->f_count++; 47245923Smckusick if (fd > fdp->fd_lastfile) 47345923Smckusick fdp->fd_lastfile = fd; 47443452Shibler *retval = fd; 47544421Skarels return (0); 47641486Smckusick } 47741486Smckusick 47854917Storek struct hpuxutssys_args { 47954917Storek struct hpuxutsname *uts; 48054917Storek int dev; 48154917Storek int request; 48254917Storek }; 48345753Smckusick hpuxutssys(p, uap, retval) 48443452Shibler struct proc *p; 48554917Storek register struct hpuxutssys_args *uap; 48643452Shibler int *retval; 48743452Shibler { 48841486Smckusick register int i; 48943452Shibler int error; 49041486Smckusick 49141486Smckusick switch (uap->request) { 49241486Smckusick /* uname */ 49341486Smckusick case 0: 49441486Smckusick /* fill in machine type */ 49541486Smckusick switch (machineid) { 49641486Smckusick case HP_320: 49741486Smckusick protoutsname.machine[6] = '2'; 49841486Smckusick break; 49941486Smckusick /* includes 318 and 319 */ 50041486Smckusick case HP_330: 50141486Smckusick protoutsname.machine[6] = '3'; 50241486Smckusick break; 50341486Smckusick case HP_340: 50441486Smckusick protoutsname.machine[6] = '4'; 50541486Smckusick break; 50641486Smckusick case HP_350: 50741486Smckusick protoutsname.machine[6] = '5'; 50841486Smckusick break; 50941486Smckusick case HP_360: 51041486Smckusick protoutsname.machine[6] = '6'; 51141486Smckusick break; 51241486Smckusick case HP_370: 51341486Smckusick protoutsname.machine[6] = '7'; 51441486Smckusick break; 51543452Shibler /* includes 345 */ 51643452Shibler case HP_375: 51743452Shibler protoutsname.machine[6] = '7'; 51843452Shibler protoutsname.machine[7] = '5'; 51943452Shibler break; 52054857Shibler /* includes 425 */ 52154857Shibler case HP_380: 52254857Shibler protoutsname.machine[6] = '8'; 52354857Shibler break; 524*57307Shibler case HP_433: 525*57307Shibler protoutsname.machine[5] = '4'; 526*57307Shibler protoutsname.machine[6] = '3'; 527*57307Shibler protoutsname.machine[7] = '3'; 528*57307Shibler break; 52941486Smckusick } 53041486Smckusick /* copy hostname (sans domain) to nodename */ 53149329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 53241486Smckusick protoutsname.nodename[i] = hostname[i]; 53349329Shibler protoutsname.nodename[i] = '\0'; 53443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 53543452Shibler sizeof(struct hpuxutsname)); 53641486Smckusick break; 53745753Smckusick 53845753Smckusick /* gethostname */ 53945753Smckusick case 5: 54045753Smckusick /* uap->dev is length */ 54145753Smckusick if (uap->dev > hostnamelen + 1) 54245753Smckusick uap->dev = hostnamelen + 1; 54345753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 54445753Smckusick uap->dev); 54545753Smckusick break; 54645753Smckusick 54745753Smckusick case 1: /* ?? */ 54845753Smckusick case 2: /* ustat */ 54945753Smckusick case 3: /* ?? */ 55045753Smckusick case 4: /* sethostname */ 55141486Smckusick default: 55243452Shibler error = EINVAL; 55341486Smckusick break; 55441486Smckusick } 55544421Skarels return (error); 55641486Smckusick } 55741486Smckusick 55854917Storek struct hpuxsysconf_args { 55954917Storek int name; 56054917Storek }; 56153922Shibler hpuxsysconf(p, uap, retval) 56253922Shibler struct proc *p; 56354917Storek struct hpuxsysconf_args *uap; 56453922Shibler int *retval; 56553922Shibler { 56653922Shibler switch (uap->name) { 56753922Shibler 56853922Shibler /* open files */ 56953922Shibler case HPUX_SYSCONF_OPENMAX: 57053922Shibler *retval = NOFILE; 57153922Shibler break; 57253922Shibler 57353922Shibler /* architecture */ 57453922Shibler case HPUX_SYSCONF_CPUTYPE: 57553922Shibler switch (machineid) { 57653922Shibler case HP_320: 57753922Shibler case HP_330: 57853922Shibler case HP_350: 57953922Shibler *retval = HPUX_SYSCONF_CPUM020; 58053922Shibler break; 58153922Shibler case HP_340: 58253922Shibler case HP_360: 58353922Shibler case HP_370: 58453922Shibler case HP_375: 58553922Shibler *retval = HPUX_SYSCONF_CPUM030; 58653922Shibler break; 58753922Shibler case HP_380: 588*57307Shibler case HP_433: 58953922Shibler *retval = HPUX_SYSCONF_CPUM040; 59053922Shibler break; 59153922Shibler } 59253922Shibler break; 59353922Shibler default: 59454857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 59553922Shibler return (EINVAL); 59653922Shibler } 59753922Shibler return (0); 59853922Shibler } 59953922Shibler 60054917Storek struct hpuxstat_args { 60154917Storek char *fname; 60254917Storek struct hpuxstat *hsb; 60354917Storek }; 60443452Shibler hpuxstat(p, uap, retval) 60543452Shibler struct proc *p; 60654917Storek struct hpuxstat_args *uap; 60743452Shibler int *retval; 60843452Shibler { 60955282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 61041486Smckusick } 61141486Smckusick 61254917Storek struct hpuxlstat_args { 61354917Storek char *fname; 61454917Storek struct hpuxstat *hsb; 61554917Storek }; 61643452Shibler hpuxlstat(p, uap, retval) 61743452Shibler struct proc *p; 61854917Storek struct hpuxlstat_args *uap; 61943452Shibler int *retval; 62041486Smckusick { 62155282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 62241486Smckusick } 62341486Smckusick 62454917Storek struct hpuxfstat_args { 62554917Storek int fdes; 62654917Storek struct hpuxstat *hsb; 62754917Storek }; 62843452Shibler hpuxfstat(p, uap, retval) 62943452Shibler struct proc *p; 63054917Storek register struct hpuxfstat_args *uap; 63143452Shibler int *retval; 63241486Smckusick { 63345923Smckusick register struct filedesc *fdp = p->p_fd; 63441486Smckusick register struct file *fp; 63541486Smckusick struct stat sb; 63643452Shibler int error; 63741486Smckusick 63848478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 63948478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 64044421Skarels return (EBADF); 64143452Shibler 64241486Smckusick switch (fp->f_type) { 64341486Smckusick 64441486Smckusick case DTYPE_VNODE: 64555282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 64641486Smckusick break; 64741486Smckusick 64841486Smckusick case DTYPE_SOCKET: 64955282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 65041486Smckusick break; 65141486Smckusick 65241486Smckusick default: 65341486Smckusick panic("fstat"); 65441486Smckusick /*NOTREACHED*/ 65541486Smckusick } 65641486Smckusick /* is this right for sockets?? */ 65743452Shibler if (error == 0) 65843452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 65944421Skarels return (error); 66041486Smckusick } 66141486Smckusick 66254917Storek struct hpuxulimit_args { 66354917Storek int cmd; 66454917Storek long newlimit; 66554917Storek }; 66643452Shibler hpuxulimit(p, uap, retval) 66743452Shibler struct proc *p; 66854917Storek register struct hpuxulimit_args *uap; 66953481Smckusick long *retval; 67043452Shibler { 67141486Smckusick struct rlimit *limp; 67243452Shibler int error = 0; 67341486Smckusick 67448478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 67541486Smckusick switch (uap->cmd) { 67641486Smckusick case 2: 67741486Smckusick uap->newlimit *= 512; 67841486Smckusick if (uap->newlimit > limp->rlim_max && 67948478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 68041486Smckusick break; 68141486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 68241486Smckusick /* else fall into... */ 68341486Smckusick 68441486Smckusick case 1: 68545753Smckusick *retval = limp->rlim_max / 512; 68641486Smckusick break; 68741486Smckusick 68841486Smckusick case 3: 68948478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 69048478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 69141486Smckusick break; 69241486Smckusick 69341486Smckusick default: 69443452Shibler error = EINVAL; 69541486Smckusick break; 69641486Smckusick } 69744421Skarels return (error); 69841486Smckusick } 69941486Smckusick 70041486Smckusick /* 70141486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 70241486Smckusick * values -16 (high) thru -1 (low). 70341486Smckusick */ 70454917Storek struct hpuxrtprio_args { 70554917Storek int pid; 70654917Storek int prio; 70754917Storek }; 70843452Shibler hpuxrtprio(cp, uap, retval) 70943452Shibler struct proc *cp; 71054917Storek register struct hpuxrtprio_args *uap; 71143452Shibler int *retval; 71243452Shibler { 71341486Smckusick struct proc *p; 71443452Shibler int nice, error; 71541486Smckusick 71641486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 71743452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 71844421Skarels return (EINVAL); 71941486Smckusick if (uap->pid == 0) 72043452Shibler p = cp; 72143452Shibler else if ((p = pfind(uap->pid)) == 0) 72244421Skarels return (ESRCH); 72341486Smckusick nice = p->p_nice; 72441486Smckusick if (nice < NZERO) 72543452Shibler *retval = (nice + 16) << 3; 72641486Smckusick else 72743452Shibler *retval = RTPRIO_RTOFF; 72841486Smckusick switch (uap->prio) { 72941486Smckusick 73041486Smckusick case RTPRIO_NOCHG: 73144421Skarels return (0); 73241486Smckusick 73341486Smckusick case RTPRIO_RTOFF: 73441486Smckusick if (nice >= NZERO) 73544421Skarels return (0); 73641486Smckusick nice = NZERO; 73741486Smckusick break; 73841486Smckusick 73941486Smckusick default: 74041486Smckusick nice = (uap->prio >> 3) - 16; 74141486Smckusick break; 74241486Smckusick } 74343452Shibler error = donice(cp, p, nice); 74443452Shibler if (error == EACCES) 74543452Shibler error = EPERM; 74644421Skarels return (error); 74741486Smckusick } 74841486Smckusick 74954917Storek struct hpuxadvise_args { 75054917Storek int arg; 75154917Storek }; 75243452Shibler hpuxadvise(p, uap, retval) 75343452Shibler struct proc *p; 75454917Storek struct hpuxadvise_args *uap; 75543452Shibler int *retval; 75641486Smckusick { 75743452Shibler int error = 0; 75841486Smckusick 75941486Smckusick switch (uap->arg) { 76041486Smckusick case 0: 761*57307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 76241486Smckusick break; 76341486Smckusick case 1: 76441486Smckusick ICIA(); 76541486Smckusick break; 76641486Smckusick case 2: 76741486Smckusick DCIA(); 76841486Smckusick break; 76941486Smckusick default: 77043452Shibler error = EINVAL; 77141486Smckusick break; 77241486Smckusick } 77344421Skarels return (error); 77441486Smckusick } 77541486Smckusick 77654917Storek struct hpuxptrace_args { 77754917Storek int req; 77854917Storek int pid; 77954917Storek int *addr; 78054917Storek int data; 78154917Storek }; 78243452Shibler hpuxptrace(p, uap, retval) 78343452Shibler struct proc *p; 78454917Storek struct hpuxptrace_args *uap; 78543452Shibler int *retval; 78643452Shibler { 787*57307Shibler int error, isps = 0; 788*57307Shibler struct proc *cp; 78941486Smckusick 790*57307Shibler switch (uap->req) { 791*57307Shibler /* map signal */ 792*57307Shibler case PT_STEP: 793*57307Shibler case PT_CONTINUE: 79441486Smckusick if (uap->data) { 79541486Smckusick uap->data = hpuxtobsdsig(uap->data); 79641486Smckusick if (uap->data == 0) 79741486Smckusick uap->data = NSIG; 79841486Smckusick } 799*57307Shibler break; 800*57307Shibler /* map u-area offset */ 801*57307Shibler case PT_READ_U: 802*57307Shibler case PT_WRITE_U: 803*57307Shibler /* 804*57307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 805*57307Shibler * to be called in the child context (procxmt) but we 806*57307Shibler * do it here in the parent context to avoid hacks in 807*57307Shibler * the MI sys_process.c file. This works only because 808*57307Shibler * we can access the child's md_regs pointer and it 809*57307Shibler * has the correct value (the child has already trapped 810*57307Shibler * into the kernel). 811*57307Shibler */ 812*57307Shibler if ((cp = pfind(uap->pid)) == 0) 813*57307Shibler return (ESRCH); 814*57307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 815*57307Shibler 816*57307Shibler /* 817*57307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 818*57307Shibler * to write PS actually contain the PS in the high word 819*57307Shibler * and the high half of the PC (the following register) 820*57307Shibler * in the low word. Move the PS value to where BSD 821*57307Shibler * expects it. 822*57307Shibler */ 823*57307Shibler if (isps && uap->req == PT_WRITE_U) 824*57307Shibler uap->data >>= 16; 825*57307Shibler break; 82641486Smckusick } 82743452Shibler error = ptrace(p, uap, retval); 828*57307Shibler /* 829*57307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 830*57307Shibler * Note that we do not return the high part of PC like HP-UX 831*57307Shibler * would, but the HP-UX debuggers don't require it. 832*57307Shibler */ 833*57307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 834*57307Shibler *retval <<= 16; 83544421Skarels return (error); 83641486Smckusick } 83741486Smckusick 83854917Storek struct hpuxgetdomainname_args { 83954917Storek char *domainname; 84054917Storek u_int len; 84154917Storek }; 84243452Shibler hpuxgetdomainname(p, uap, retval) 84343452Shibler struct proc *p; 84454917Storek register struct hpuxgetdomainname_args *uap; 84543452Shibler int *retval; 84643452Shibler { 84741486Smckusick if (uap->len > domainnamelen + 1) 84841486Smckusick uap->len = domainnamelen + 1; 84944421Skarels return (copyout(domainname, uap->domainname, uap->len)); 85041486Smckusick } 85141486Smckusick 85254917Storek struct hpuxsetdomainname_args { 85354917Storek char *domainname; 85454917Storek u_int len; 85554917Storek }; 85643452Shibler hpuxsetdomainname(p, uap, retval) 85743452Shibler struct proc *p; 85854917Storek register struct hpuxsetdomainname_args *uap; 85943452Shibler int *retval; 86043452Shibler { 86143452Shibler int error; 86241486Smckusick 86348478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 86444421Skarels return (error); 86543452Shibler if (uap->len > sizeof (domainname) - 1) 86644421Skarels return (EINVAL); 86741486Smckusick domainnamelen = uap->len; 86843452Shibler error = copyin(uap->domainname, domainname, uap->len); 86941486Smckusick domainname[domainnamelen] = 0; 87044421Skarels return (error); 87141486Smckusick } 87241486Smckusick 87341486Smckusick #ifdef SYSVSHM 87456506Sbostic #include <sys/shm.h> 87554857Shibler 87643452Shibler hpuxshmat(p, uap, retval) 87743452Shibler struct proc *p; 87843452Shibler int *uap, *retval; 87941486Smckusick { 88044421Skarels return (shmat(p, uap, retval)); 88141486Smckusick } 88241486Smckusick 88343452Shibler hpuxshmdt(p, uap, retval) 88443452Shibler struct proc *p; 88543452Shibler int *uap, *retval; 88641486Smckusick { 88744421Skarels return (shmdt(p, uap, retval)); 88841486Smckusick } 88941486Smckusick 89043452Shibler hpuxshmget(p, uap, retval) 89143452Shibler struct proc *p; 89243452Shibler int *uap, *retval; 89341486Smckusick { 89444421Skarels return (shmget(p, uap, retval)); 89541486Smckusick } 89654857Shibler 89754857Shibler /* 89854857Shibler * Handle HP-UX specific commands. 89954857Shibler */ 90054917Storek struct hpuxshmctl_args { 90154917Storek int shmid; 90254917Storek int cmd; 90354917Storek caddr_t buf; 90454917Storek }; 90554857Shibler hpuxshmctl(p, uap, retval) 90654857Shibler struct proc *p; 90754917Storek struct hpuxshmctl_args *uap; 90854857Shibler int *retval; 90954857Shibler { 91054857Shibler register struct shmid_ds *shp; 91154857Shibler register struct ucred *cred = p->p_ucred; 91254857Shibler int error; 91354857Shibler 91454857Shibler if (error = shmvalid(uap->shmid)) 91554857Shibler return (error); 91654857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 91754857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 91854857Shibler /* don't really do anything, but make them think we did */ 91954857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 92054857Shibler cred->cr_uid != shp->shm_perm.cuid) 92154857Shibler return (EPERM); 92254857Shibler return (0); 92354857Shibler } 92454857Shibler return (shmctl(p, uap, retval)); 92554857Shibler } 92641486Smckusick #endif 92741486Smckusick 92841486Smckusick /* 92941486Smckusick * Fake semaphore routines, just don't return an error. 93041486Smckusick * Should be adequate for starbase to run. 93141486Smckusick */ 93254917Storek struct hpuxsemctl_args { 93354917Storek int semid; 93454917Storek u_int semnum; 93554917Storek int cmd; 93654917Storek int arg; 93754917Storek }; 93843452Shibler hpuxsemctl(p, uap, retval) 93943452Shibler struct proc *p; 94054917Storek struct hpuxsemctl_args *uap; 94143452Shibler int *retval; 94243452Shibler { 94341486Smckusick /* XXX: should do something here */ 94444421Skarels return (0); 94541486Smckusick } 94641486Smckusick 94754917Storek struct hpuxsemget_args { 94854917Storek key_t key; 94954917Storek int nsems; 95054917Storek int semflg; 95154917Storek }; 95243452Shibler hpuxsemget(p, uap, retval) 95343452Shibler struct proc *p; 95454917Storek struct hpuxsemget_args *uap; 95543452Shibler int *retval; 95643452Shibler { 95741486Smckusick /* XXX: should do something here */ 95844421Skarels return (0); 95941486Smckusick } 96041486Smckusick 96154917Storek struct hpuxsemop_args { 96254917Storek int semid; 96354917Storek struct sembuf *sops; 96454917Storek u_int nsops; 96554917Storek }; 96643452Shibler hpuxsemop(p, uap, retval) 96743452Shibler struct proc *p; 96854917Storek struct hpuxsemop_args *uap; 96943452Shibler int *retval; 97043452Shibler { 97141486Smckusick /* XXX: should do something here */ 97244421Skarels return (0); 97341486Smckusick } 97441486Smckusick 975*57307Shibler /* 976*57307Shibler * HP-UX mmap() emulation (mainly for shared library support). 977*57307Shibler */ 978*57307Shibler struct hpuxmmap_args { 979*57307Shibler caddr_t addr; 980*57307Shibler int len; 981*57307Shibler int prot; 982*57307Shibler int flags; 983*57307Shibler int fd; 984*57307Shibler long pos; 985*57307Shibler }; 986*57307Shibler hpuxmmap(p, uap, retval) 987*57307Shibler struct proc *p; 988*57307Shibler struct hpuxmmap_args *uap; 989*57307Shibler int *retval; 990*57307Shibler { 991*57307Shibler struct mmap_args { 992*57307Shibler caddr_t addr; 993*57307Shibler int len; 994*57307Shibler int prot; 995*57307Shibler int flags; 996*57307Shibler int fd; 997*57307Shibler long pad; 998*57307Shibler off_t pos; 999*57307Shibler } nargs; 1000*57307Shibler 1001*57307Shibler nargs.addr = uap->addr; 1002*57307Shibler nargs.len = uap->len; 1003*57307Shibler nargs.prot = uap->prot; 1004*57307Shibler nargs.flags = uap->flags & 1005*57307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 1006*57307Shibler if (uap->flags & HPUXMAP_FIXED) 1007*57307Shibler nargs.flags |= MAP_FIXED; 1008*57307Shibler if (uap->flags & HPUXMAP_ANON) 1009*57307Shibler nargs.flags |= MAP_ANON; 1010*57307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 1011*57307Shibler nargs.pos = uap->pos; 1012*57307Shibler return (smmap(p, &nargs, retval)); 1013*57307Shibler } 1014*57307Shibler 101554857Shibler /* convert from BSD to HP-UX errno */ 101641486Smckusick bsdtohpuxerrno(err) 101741486Smckusick int err; 101841486Smckusick { 101941486Smckusick if (err < 0 || err >= NERR) 102041486Smckusick return(BERR); 102141486Smckusick return((int)bsdtohpuxerrnomap[err]); 102241486Smckusick } 102341486Smckusick 102455282Smckusick hpuxstat1(fname, hsb, follow, p) 102541486Smckusick char *fname; 102641486Smckusick struct hpuxstat *hsb; 102741486Smckusick int follow; 102855282Smckusick struct proc *p; 102941486Smckusick { 103048478Skarels int error; 103141486Smckusick struct stat sb; 103248478Skarels struct nameidata nd; 103341486Smckusick 103455282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 103552330Smckusick if (error = namei(&nd)) 103641486Smckusick return (error); 103755282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 103852330Smckusick vput(nd.ni_vp); 103941486Smckusick if (error == 0) 104041486Smckusick error = bsdtohpuxstat(&sb, hsb); 104141486Smckusick return (error); 104241486Smckusick } 104341486Smckusick 104441486Smckusick #include "grf.h" 104553922Shibler #if NGRF > 0 104653922Shibler #ifdef __STDC__ 104753922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 104853922Shibler #else 104953922Shibler extern int grfopen(); 105053922Shibler #endif 105153922Shibler #endif 105241486Smckusick 105353922Shibler #define NHIL 1 /* XXX */ 105453922Shibler #if NHIL > 0 105553922Shibler #ifdef __STDC__ 105653922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 105753922Shibler #else 105853922Shibler extern int hilopen(); 105953922Shibler #endif 106053922Shibler #endif 106153922Shibler 106256506Sbostic #include <sys/conf.h> 106353922Shibler 106441486Smckusick bsdtohpuxstat(sb, hsb) 106541486Smckusick struct stat *sb; 106641486Smckusick struct hpuxstat *hsb; 106741486Smckusick { 106841486Smckusick struct hpuxstat ds; 106941486Smckusick 107041486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 107153481Smckusick ds.hst_dev = (u_short)sb->st_dev; 107241486Smckusick ds.hst_ino = (u_long)sb->st_ino; 107341486Smckusick ds.hst_mode = sb->st_mode; 107441486Smckusick ds.hst_nlink = sb->st_nlink; 107541486Smckusick ds.hst_uid = (u_short)sb->st_uid; 107641486Smckusick ds.hst_gid = (u_short)sb->st_gid; 1077*57307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 1078*57307Shibler 107953922Shibler /* XXX: I don't want to talk about it... */ 108053922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 108141486Smckusick #if NGRF > 0 108253922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 108353922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 108441486Smckusick #endif 108553922Shibler #if NHIL > 0 108653922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 108753922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 108853922Shibler #endif 108953922Shibler ; 1090*57307Shibler } 109153481Smckusick if (sb->st_size < (quad_t)1 << 32) 109253481Smckusick ds.hst_size = (long)sb->st_size; 109353481Smckusick else 109453481Smckusick ds.hst_size = -2; 109541486Smckusick ds.hst_atime = sb->st_atime; 109641486Smckusick ds.hst_mtime = sb->st_mtime; 109741486Smckusick ds.hst_ctime = sb->st_ctime; 109841486Smckusick ds.hst_blksize = sb->st_blksize; 109941486Smckusick ds.hst_blocks = sb->st_blocks; 110041486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 110141486Smckusick } 110241486Smckusick 110341486Smckusick hpuxtobsdioctl(com) 110441486Smckusick int com; 110541486Smckusick { 110641486Smckusick switch (com) { 110741486Smckusick case HPUXTIOCSLTC: 110841486Smckusick com = TIOCSLTC; break; 110941486Smckusick case HPUXTIOCGLTC: 111041486Smckusick com = TIOCGLTC; break; 111141486Smckusick case HPUXTIOCSPGRP: 111241486Smckusick com = TIOCSPGRP; break; 111341486Smckusick case HPUXTIOCGPGRP: 111441486Smckusick com = TIOCGPGRP; break; 111541486Smckusick case HPUXTIOCLBIS: 111641486Smckusick com = TIOCLBIS; break; 111741486Smckusick case HPUXTIOCLBIC: 111841486Smckusick com = TIOCLBIC; break; 111941486Smckusick case HPUXTIOCLSET: 112041486Smckusick com = TIOCLSET; break; 112141486Smckusick case HPUXTIOCLGET: 112241486Smckusick com = TIOCLGET; break; 112341486Smckusick } 112441486Smckusick return(com); 112541486Smckusick } 112641486Smckusick 112741486Smckusick /* 112854857Shibler * HP-UX ioctl system call. The differences here are: 112941486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 113049329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 113141486Smckusick * the sgttyb struct is 2 bytes longer 113241486Smckusick */ 113354917Storek struct hpuxioctl_args { 113454917Storek int fdes; 113554917Storek int cmd; 113654917Storek caddr_t cmarg; 113754917Storek }; 113843452Shibler hpuxioctl(p, uap, retval) 113943452Shibler struct proc *p; 114054917Storek register struct hpuxioctl_args *uap; 114143452Shibler int *retval; 114243452Shibler { 114345923Smckusick register struct filedesc *fdp = p->p_fd; 114443452Shibler register struct file *fp; 114543452Shibler register int com, error; 114641486Smckusick register u_int size; 114741486Smckusick caddr_t memp = 0; 114841486Smckusick #define STK_PARAMS 128 114941486Smckusick char stkbuf[STK_PARAMS]; 115041486Smckusick caddr_t data = stkbuf; 115141486Smckusick 115241486Smckusick com = uap->cmd; 115341486Smckusick 115441486Smckusick /* XXX */ 115543452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 115645923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 115741486Smckusick 115848478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 115948478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 116044421Skarels return (EBADF); 116143452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 116244421Skarels return (EBADF); 116341486Smckusick 116441486Smckusick /* 116541486Smckusick * Interpret high order word to find 116641486Smckusick * amount of data to be copied to/from the 116741486Smckusick * user's address space. 116841486Smckusick */ 116941486Smckusick size = IOCPARM_LEN(com); 117043452Shibler if (size > IOCPARM_MAX) 117144421Skarels return (ENOTTY); 117241486Smckusick if (size > sizeof (stkbuf)) { 117343452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 117441486Smckusick data = memp; 117541486Smckusick } 117641486Smckusick if (com&IOC_IN) { 117741486Smckusick if (size) { 117843452Shibler error = copyin(uap->cmarg, data, (u_int)size); 117943452Shibler if (error) { 118041486Smckusick if (memp) 118141486Smckusick free(memp, M_IOCTLOPS); 118244421Skarels return (error); 118341486Smckusick } 118441486Smckusick } else 118541486Smckusick *(caddr_t *)data = uap->cmarg; 118641486Smckusick } else if ((com&IOC_OUT) && size) 118741486Smckusick /* 118843452Shibler * Zero the buffer so the user always 118943452Shibler * gets back something deterministic. 119041486Smckusick */ 119141486Smckusick bzero(data, size); 119241486Smckusick else if (com&IOC_VOID) 119341486Smckusick *(caddr_t *)data = uap->cmarg; 119441486Smckusick 119541486Smckusick switch (com) { 119641486Smckusick 119749329Shibler case HPUXFIOSNBIO: 119849329Shibler { 119949329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 120049329Shibler int tmp; 120149329Shibler 120249329Shibler if (*(int *)data) 120349329Shibler *ofp |= UF_FIONBIO_ON; 120449329Shibler else 120549329Shibler *ofp &= ~UF_FIONBIO_ON; 120649329Shibler /* 120749950Smckusick * Only set/clear if FNONBLOCK not in effect 120849329Shibler */ 120949329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 121049950Smckusick tmp = fp->f_flag & FNONBLOCK; 121149329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 121249329Shibler (caddr_t)&tmp, p); 121349329Shibler } 121449329Shibler break; 121549329Shibler } 121649329Shibler 121741486Smckusick case HPUXTIOCCONS: 121841486Smckusick *(int *)data = 1; 121948478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 122041486Smckusick break; 122141486Smckusick 122241486Smckusick /* BSD-style job control ioctls */ 122341486Smckusick case HPUXTIOCLBIS: 122441486Smckusick case HPUXTIOCLBIC: 122541486Smckusick case HPUXTIOCLSET: 122641486Smckusick *(int *)data &= HPUXLTOSTOP; 122741486Smckusick if (*(int *)data & HPUXLTOSTOP) 122841486Smckusick *(int *)data = LTOSTOP; 122941486Smckusick /* fall into */ 123041486Smckusick case HPUXTIOCLGET: 123141486Smckusick case HPUXTIOCSLTC: 123241486Smckusick case HPUXTIOCGLTC: 123341486Smckusick case HPUXTIOCSPGRP: 123441486Smckusick case HPUXTIOCGPGRP: 123548478Skarels error = (*fp->f_ops->fo_ioctl) 123648478Skarels (fp, hpuxtobsdioctl(com), data, p); 123743452Shibler if (error == 0 && com == HPUXTIOCLGET) { 123841486Smckusick *(int *)data &= LTOSTOP; 123941486Smckusick if (*(int *)data & LTOSTOP) 124041486Smckusick *(int *)data = HPUXLTOSTOP; 124141486Smckusick } 124241486Smckusick break; 124341486Smckusick 124455832Shibler /* SYS 5 termio and POSIX termios */ 124541486Smckusick case HPUXTCGETA: 124641486Smckusick case HPUXTCSETA: 124741486Smckusick case HPUXTCSETAW: 124841486Smckusick case HPUXTCSETAF: 124955832Shibler case HPUXTCGETATTR: 125055832Shibler case HPUXTCSETATTR: 125155832Shibler case HPUXTCSETATTRD: 125255832Shibler case HPUXTCSETATTRF: 125348478Skarels error = hpuxtermio(fp, com, data, p); 125441486Smckusick break; 125541486Smckusick 125641486Smckusick default: 125748478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 125841486Smckusick break; 125941486Smckusick } 126041486Smckusick /* 126141486Smckusick * Copy any data to user, size was 126241486Smckusick * already set and checked above. 126341486Smckusick */ 126443452Shibler if (error == 0 && (com&IOC_OUT) && size) 126543452Shibler error = copyout(data, uap->cmarg, (u_int)size); 126641486Smckusick if (memp) 126741486Smckusick free(memp, M_IOCTLOPS); 126844421Skarels return (error); 126941486Smckusick } 127041486Smckusick 127141486Smckusick /* 127241486Smckusick * Man page lies, behaviour here is based on observed behaviour. 127341486Smckusick */ 127454917Storek struct hpuxgetcontext_args { 127554917Storek char *buf; 127654917Storek int len; 127754917Storek }; 127843452Shibler hpuxgetcontext(p, uap, retval) 127943452Shibler struct proc *p; 128054917Storek struct hpuxgetcontext_args *uap; 128143452Shibler int *retval; 128243452Shibler { 128341486Smckusick int error = 0; 128441486Smckusick register int len; 128541486Smckusick 128653922Shibler #if defined(HP380) 128753922Shibler if (machineid == HP_380) { 128855072Spendry len = min(uap->len, sizeof(hpux040context)); 128953922Shibler if (len) 129053922Shibler error = copyout(hpux040context, uap->buf, len); 129153922Shibler if (error == 0) 129253922Shibler *retval = sizeof(hpux040context); 129353922Shibler return (error); 129453922Shibler } 129553922Shibler #endif 129655072Spendry len = min(uap->len, sizeof(hpuxcontext)); 129741486Smckusick if (len) 129841486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 129943452Shibler if (error == 0) 130043452Shibler *retval = sizeof(hpuxcontext); 130144421Skarels return (error); 130241486Smckusick } 130341486Smckusick 130441486Smckusick /* 130541486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 130641486Smckusick * Note we do not check the real uid or "saved" uid. 130741486Smckusick */ 130854917Storek struct hpuxgetpgrp2_args { 130954917Storek int pid; 131054917Storek }; 131143452Shibler hpuxgetpgrp2(cp, uap, retval) 131243452Shibler struct proc *cp; 131354917Storek register struct hpuxgetpgrp2_args *uap; 131443452Shibler int *retval; 131541486Smckusick { 131641486Smckusick register struct proc *p; 131741486Smckusick 131841486Smckusick if (uap->pid == 0) 131943452Shibler uap->pid = cp->p_pid; 132041486Smckusick p = pfind(uap->pid); 132143452Shibler if (p == 0) 132244421Skarels return (ESRCH); 132348478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 132448478Skarels !inferior(p)) 132544421Skarels return (EPERM); 132643452Shibler *retval = p->p_pgid; 132744421Skarels return (0); 132841486Smckusick } 132941486Smckusick 133041486Smckusick /* 133141486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 133241486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 133341486Smckusick */ 133454917Storek struct hpuxsetpgrp2_args { 133554917Storek int pid; 133654917Storek int pgrp; 133754917Storek }; 133843452Shibler hpuxsetpgrp2(p, uap, retval) 133943452Shibler struct proc *p; 134054917Storek struct hpuxsetpgrp2_args *uap; 134143452Shibler int *retval; 134243452Shibler { 134341486Smckusick /* empirically determined */ 134443452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 134544421Skarels return (EINVAL); 134648478Skarels return (setpgid(p, uap, retval)); 134741486Smckusick } 134841486Smckusick 134941486Smckusick /* 135055165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 135145753Smckusick */ 135254917Storek struct hpuxsetresuid_args { 135354917Storek int ruid; 135454917Storek int euid; 135554917Storek int suid; 135654917Storek }; 135745753Smckusick hpuxsetresuid(p, uap, retval) 135855165Smckusick struct proc *p; 135954917Storek struct hpuxsetresuid_args *uap; 136045753Smckusick int *retval; 136145753Smckusick { 136255165Smckusick return (osetreuid(p, uap, retval)); 136345753Smckusick } 136445753Smckusick 136554917Storek struct hpuxsetresgid_args { 136654917Storek int rgid; 136754917Storek int egid; 136854917Storek int sgid; 136954917Storek }; 137045753Smckusick hpuxsetresgid(p, uap, retval) 137155165Smckusick struct proc *p; 137254917Storek struct hpuxsetresgid_args *uap; 137345753Smckusick int *retval; 137445753Smckusick { 137555165Smckusick return (osetregid(p, uap, retval)); 137645753Smckusick } 137745753Smckusick 1378*57307Shibler struct hpuxrlimit_args { 1379*57307Shibler u_int which; 1380*57307Shibler struct orlimit *rlp; 1381*57307Shibler }; 1382*57307Shibler hpuxgetrlimit(p, uap, retval) 1383*57307Shibler struct proc *p; 1384*57307Shibler struct hpuxrlimit_args *uap; 1385*57307Shibler int *retval; 1386*57307Shibler { 1387*57307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 1388*57307Shibler return (EINVAL); 1389*57307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 1390*57307Shibler uap->which = RLIMIT_NOFILE; 1391*57307Shibler return (getrlimit(p, uap, retval)); 1392*57307Shibler } 1393*57307Shibler 1394*57307Shibler hpuxsetrlimit(p, uap, retval) 1395*57307Shibler struct proc *p; 1396*57307Shibler struct hpuxrlimit_args *uap; 1397*57307Shibler int *retval; 1398*57307Shibler { 1399*57307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 1400*57307Shibler return (EINVAL); 1401*57307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 1402*57307Shibler uap->which = RLIMIT_NOFILE; 1403*57307Shibler return (setrlimit(p, uap, retval)); 1404*57307Shibler } 1405*57307Shibler 140645753Smckusick /* 140745753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 140845753Smckusick */ 140954917Storek struct hpuxlockf_args { 141054917Storek int fd; 141154917Storek int func; 141254917Storek long size; 141354917Storek }; 141445753Smckusick hpuxlockf(p, uap, retval) 141545753Smckusick struct proc *p; 141654917Storek struct hpuxlockf_args *uap; 141745753Smckusick int *retval; 141845753Smckusick { 141945753Smckusick return (0); 142045753Smckusick } 142145753Smckusick 142254917Storek struct hpuxgetaccess_args { 142354917Storek char *path; 142454917Storek int uid; 142554917Storek int ngroups; 142654917Storek int *gidset; 142754917Storek void *label; 142854917Storek void *privs; 142954917Storek }; 143045753Smckusick hpuxgetaccess(p, uap, retval) 143145753Smckusick register struct proc *p; 143254917Storek register struct hpuxgetaccess_args *uap; 143345753Smckusick int *retval; 143445753Smckusick { 143545753Smckusick int lgroups[NGROUPS]; 143645753Smckusick int error = 0; 143745753Smckusick register struct ucred *cred; 143845753Smckusick register struct vnode *vp; 143952330Smckusick struct nameidata nd; 144045753Smckusick 144145753Smckusick /* 144245753Smckusick * Build an appropriate credential structure 144345753Smckusick */ 144448478Skarels cred = crdup(p->p_ucred); 144545753Smckusick switch (uap->uid) { 144645753Smckusick case 65502: /* UID_EUID */ 144745753Smckusick break; 144845753Smckusick case 65503: /* UID_RUID */ 144948478Skarels cred->cr_uid = p->p_cred->p_ruid; 145045753Smckusick break; 145145753Smckusick case 65504: /* UID_SUID */ 145245753Smckusick error = EINVAL; 145345753Smckusick break; 145445753Smckusick default: 145545753Smckusick if (uap->uid > 65504) 145645753Smckusick error = EINVAL; 145745753Smckusick cred->cr_uid = uap->uid; 145845753Smckusick break; 145945753Smckusick } 146045753Smckusick switch (uap->ngroups) { 146145753Smckusick case -1: /* NGROUPS_EGID */ 146245753Smckusick cred->cr_ngroups = 1; 146345753Smckusick break; 146445753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 146545753Smckusick break; 146645753Smckusick case -2: /* NGROUPS_RGID */ 146745753Smckusick cred->cr_ngroups = 1; 146848478Skarels cred->cr_gid = p->p_cred->p_rgid; 146945753Smckusick break; 147045753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 147148478Skarels cred->cr_gid = p->p_cred->p_rgid; 147245753Smckusick break; 147345753Smckusick case -3: /* NGROUPS_SGID */ 147445753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 147545753Smckusick error = EINVAL; 147645753Smckusick break; 147745753Smckusick case -4: /* NGROUPS_SUPP */ 147845753Smckusick if (cred->cr_ngroups > 1) 147945753Smckusick cred->cr_gid = cred->cr_groups[1]; 148045753Smckusick else 148145753Smckusick error = EINVAL; 148245753Smckusick break; 148345753Smckusick default: 148445753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 148545753Smckusick error = copyin((caddr_t)uap->gidset, 148645753Smckusick (caddr_t)&lgroups[0], 148745753Smckusick uap->ngroups * sizeof(lgroups[0])); 148845753Smckusick else 148945753Smckusick error = EINVAL; 149045753Smckusick if (error == 0) { 149145753Smckusick int gid; 149245753Smckusick 149345753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 149445753Smckusick cred->cr_groups[gid] = lgroups[gid]; 149545753Smckusick cred->cr_ngroups = uap->ngroups; 149645753Smckusick } 149745753Smckusick break; 149845753Smckusick } 149945753Smckusick /* 150045753Smckusick * Lookup file using caller's effective IDs. 150145753Smckusick */ 150245753Smckusick if (error == 0) { 150352330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 150452330Smckusick uap->path, p); 150552330Smckusick error = namei(&nd); 150645753Smckusick } 150745753Smckusick if (error) { 150845753Smckusick crfree(cred); 150945753Smckusick return (error); 151045753Smckusick } 151145753Smckusick /* 151245753Smckusick * Use the constructed credentials for access checks. 151345753Smckusick */ 151452330Smckusick vp = nd.ni_vp; 151545753Smckusick *retval = 0; 151648478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 151745753Smckusick *retval |= R_OK; 151848478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 151945753Smckusick *retval |= W_OK; 152045753Smckusick /* XXX we return X_OK for root on VREG even if not */ 152148478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 152245753Smckusick *retval |= X_OK; 152345753Smckusick vput(vp); 152445753Smckusick crfree(cred); 152545753Smckusick return (error); 152645753Smckusick } 152745753Smckusick 152849134Skarels extern char kstack[]; 152941486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 153041486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 153141486Smckusick 153241486Smckusick /* simplified FP structure */ 153341486Smckusick struct bsdfp { 153441486Smckusick int save[54]; 153541486Smckusick int reg[24]; 153641486Smckusick int ctrl[3]; 153741486Smckusick }; 153841486Smckusick 1539*57307Shibler /* 1540*57307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 1541*57307Shibler */ 1542*57307Shibler hpuxtobsduoff(off, isps, p) 1543*57307Shibler int *off, *isps; 1544*57307Shibler struct proc *p; 154541486Smckusick { 1546*57307Shibler register int *ar0 = p->p_md.md_regs; 154741486Smckusick struct hpuxfp *hp; 154841486Smckusick struct bsdfp *bp; 154941486Smckusick register u_int raddr; 155041486Smckusick 1551*57307Shibler *isps = 0; 1552*57307Shibler 155348478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 155441486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 155548478Skarels return(UOFF(U_ar0)); 155641486Smckusick 155741486Smckusick #ifdef FPCOPROC 1558*57307Shibler /* FP registers from PCB */ 155941486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 156041486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 156141486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 156241486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 156341486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 156441486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 156541486Smckusick #endif 156641486Smckusick 156741486Smckusick /* 156841486Smckusick * Everything else we recognize comes from the kernel stack, 156941486Smckusick * so we convert off to an absolute address (if not already) 157041486Smckusick * for simplicity. 157141486Smckusick */ 157241486Smckusick if (off < (int *)ctob(UPAGES)) 157349134Skarels off = (int *)((u_int)off + (u_int)kstack); 157441486Smckusick 157541486Smckusick /* 1576*57307Shibler * General registers. 157754857Shibler * We know that the HP-UX registers are in the same order as ours. 157841486Smckusick * The only difference is that their PS is 2 bytes instead of a 157941486Smckusick * padded 4 like ours throwing the alignment off. 158041486Smckusick */ 158148478Skarels if (off >= ar0 && off < &ar0[18]) { 158241486Smckusick /* 158341486Smckusick * PS: return low word and high word of PC as HP-UX would 158441486Smckusick * (e.g. &u.u_ar0[16.5]). 1585*57307Shibler * 1586*57307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 1587*57307Shibler * it and passing such an offset to procxmt will cause 1588*57307Shibler * it to fail anyway. Instead, we just set the offset 1589*57307Shibler * to PS and let hpuxptrace() shift up the value returned. 159041486Smckusick */ 1591*57307Shibler if (off == &ar0[PS]) { 1592*57307Shibler #if 0 159348478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 1594*57307Shibler #else 1595*57307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 1596*57307Shibler #endif 1597*57307Shibler *isps = 1; 1598*57307Shibler } 159941486Smckusick /* 1600*57307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 1601*57307Shibler * is only 16 bits. 160241486Smckusick */ 160348478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 160448478Skarels raddr = (u_int) &ar0[PC]; 160541486Smckusick /* 160641486Smckusick * D0-D7, A0-A7: easy 160741486Smckusick */ 160841486Smckusick else 160948478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 161049134Skarels return((int)(raddr - (u_int)kstack)); 161141486Smckusick } 161241486Smckusick 161341486Smckusick /* everything else */ 161441486Smckusick return(-1); 161541486Smckusick } 161641486Smckusick 161741486Smckusick /* 161854857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 161941486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 162041486Smckusick * convert the entire user struct. 162141486Smckusick */ 162241486Smckusick hpuxdumpu(vp, cred) 162341486Smckusick struct vnode *vp; 162441486Smckusick struct ucred *cred; 162541486Smckusick { 162648478Skarels struct proc *p = curproc; 162741486Smckusick int error; 162841486Smckusick struct hpuxuser *faku; 162941486Smckusick struct bsdfp *bp; 163041486Smckusick short *foop; 163141486Smckusick 163241486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 163341486Smckusick /* 163441486Smckusick * Make sure there is no mistake about this 163541486Smckusick * being a real user structure. 163641486Smckusick */ 163741486Smckusick bzero((caddr_t)faku, ctob(1)); 163841486Smckusick /* 163941486Smckusick * Fill in the process sizes. 164041486Smckusick */ 164148478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 164248478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 164348478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 164441486Smckusick /* 164541486Smckusick * Fill in the exec header for CDB. 164641486Smckusick * This was saved back in exec(). As far as I can tell CDB 164741486Smckusick * only uses this information to verify that a particular 164841486Smckusick * core file goes with a particular binary. 164941486Smckusick */ 1650*57307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 165141486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 165241486Smckusick /* 165341486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 165454857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 165541486Smckusick * so we have to move it up. 165641486Smckusick */ 165752381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 165852381Smckusick foop = (short *) p->p_md.md_regs; 165941486Smckusick foop[32] = foop[33]; 166041486Smckusick foop[33] = foop[34]; 166141486Smckusick foop[34] = foop[35]; 166241486Smckusick #ifdef FPCOPROC 166341486Smckusick /* 166454857Shibler * Copy 68881 registers from our PCB format to HP-UX format 166541486Smckusick */ 166649134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 166741486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 166841486Smckusick sizeof(bp->save)); 166941486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 167041486Smckusick sizeof(bp->ctrl)); 167141486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 167241486Smckusick sizeof(bp->reg)); 167341486Smckusick #endif 167441486Smckusick /* 167541486Smckusick * Slay the dragon 167641486Smckusick */ 167741486Smckusick faku->hpuxu_dragon = -1; 167841486Smckusick /* 167941486Smckusick * Dump this artfully constructed page in place of the 168041486Smckusick * user struct page. 168141486Smckusick */ 168248478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 168348478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 168449134Skarels (int *)NULL, p); 168541486Smckusick /* 168641486Smckusick * Dump the remaining UPAGES-1 pages normally 168741486Smckusick */ 168841486Smckusick if (!error) 168949134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 169041486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 169149134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 169241486Smckusick free((caddr_t)faku, M_TEMP); 169341486Smckusick return(error); 169441486Smckusick } 169541486Smckusick 169641486Smckusick /* 169741486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 169841486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 169941486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 170041486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 1701*57307Shibler * 1702*57307Shibler * These are still needed as of HP-UX 7.05. 170341486Smckusick */ 170455832Shibler #ifdef COMPAT_OHPUX 170555832Shibler 170645753Smckusick #define HPUX_HZ 50 170745753Smckusick 1708*57307Shibler #include "sys/times.h" 170941486Smckusick 171041486Smckusick /* from old timeb.h */ 171141486Smckusick struct hpuxtimeb { 171241486Smckusick time_t time; 171341486Smckusick u_short millitm; 171441486Smckusick short timezone; 171541486Smckusick short dstflag; 171641486Smckusick }; 171741486Smckusick 171841486Smckusick /* ye ole stat structure */ 171941486Smckusick struct ohpuxstat { 172053481Smckusick u_short ohst_dev; 172141486Smckusick u_short ohst_ino; 172241486Smckusick u_short ohst_mode; 172341486Smckusick short ohst_nlink; 172441486Smckusick short ohst_uid; 172541486Smckusick short ohst_gid; 172653481Smckusick u_short ohst_rdev; 172741486Smckusick int ohst_size; 172841486Smckusick int ohst_atime; 172941486Smckusick int ohst_mtime; 173041486Smckusick int ohst_ctime; 173141486Smckusick }; 173241486Smckusick 173341486Smckusick /* 173441486Smckusick * SYS V style setpgrp() 173541486Smckusick */ 173643452Shibler ohpuxsetpgrp(p, uap, retval) 173743452Shibler register struct proc *p; 173843452Shibler int *uap, *retval; 173941486Smckusick { 174041486Smckusick if (p->p_pid != p->p_pgid) 174148478Skarels enterpgrp(p, p->p_pid, 0); 174243452Shibler *retval = p->p_pgid; 174345753Smckusick return (0); 174441486Smckusick } 174541486Smckusick 174654917Storek struct ohpuxtime_args { 174754917Storek long *tp; 174854917Storek }; 174943452Shibler ohpuxtime(p, uap, retval) 175043452Shibler struct proc *p; 175154917Storek register struct ohpuxtime_args *uap; 175254917Storek int *retval; 175341486Smckusick { 175445753Smckusick int error = 0; 175541486Smckusick 175641486Smckusick if (uap->tp) 175743452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 175843452Shibler sizeof (long)); 175954917Storek *(time_t *)retval = time.tv_sec; 176044421Skarels return (error); 176141486Smckusick } 176241486Smckusick 176354917Storek struct ohpuxstime_args { 176454917Storek int time; 176554917Storek }; 176643452Shibler ohpuxstime(p, uap, retval) 176743452Shibler struct proc *p; 176854917Storek register struct ohpuxstime_args *uap; 176943452Shibler int *retval; 177041486Smckusick { 177141486Smckusick struct timeval tv; 177243452Shibler int s, error; 177341486Smckusick 177441486Smckusick tv.tv_sec = uap->time; 177541486Smckusick tv.tv_usec = 0; 177648478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 177744421Skarels return (error); 177841486Smckusick 177941486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 178041486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 178141486Smckusick s = splhigh(); time = tv; splx(s); 178241486Smckusick resettodr(); 178344421Skarels return (0); 178441486Smckusick } 178541486Smckusick 178654917Storek struct ohpuxftime_args { 178754917Storek struct hpuxtimeb *tp; 178854917Storek }; 178943452Shibler ohpuxftime(p, uap, retval) 179043452Shibler struct proc *p; 179154917Storek register struct ohpuxftime_args *uap; 179243452Shibler int *retval; 179343452Shibler { 179441486Smckusick struct hpuxtimeb tb; 179541486Smckusick int s; 179641486Smckusick 179741486Smckusick s = splhigh(); 179841486Smckusick tb.time = time.tv_sec; 179941486Smckusick tb.millitm = time.tv_usec / 1000; 180041486Smckusick splx(s); 180141486Smckusick tb.timezone = tz.tz_minuteswest; 180241486Smckusick tb.dstflag = tz.tz_dsttime; 180344421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 180441486Smckusick } 180541486Smckusick 180654917Storek struct ohpuxalarm_args { 180754917Storek int deltat; 180854917Storek }; 180943452Shibler ohpuxalarm(p, uap, retval) 181043452Shibler register struct proc *p; 181154917Storek register struct ohpuxalarm_args *uap; 181243452Shibler int *retval; 181341486Smckusick { 181441486Smckusick int s = splhigh(); 181541486Smckusick 181641486Smckusick untimeout(realitexpire, (caddr_t)p); 181741486Smckusick timerclear(&p->p_realtimer.it_interval); 181843452Shibler *retval = 0; 181941486Smckusick if (timerisset(&p->p_realtimer.it_value) && 182041486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 182143452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 182241486Smckusick if (uap->deltat == 0) { 182341486Smckusick timerclear(&p->p_realtimer.it_value); 182441486Smckusick splx(s); 182544421Skarels return (0); 182641486Smckusick } 182741486Smckusick p->p_realtimer.it_value = time; 182841486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 182941486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 183041486Smckusick splx(s); 183144421Skarels return (0); 183241486Smckusick } 183341486Smckusick 183454917Storek struct ohpuxnice_args { 183554917Storek int niceness; 183654917Storek }; 183743452Shibler ohpuxnice(p, uap, retval) 183843452Shibler register struct proc *p; 183954917Storek register struct ohpuxnice_args *uap; 184043452Shibler int *retval; 184141486Smckusick { 184243452Shibler int error; 184341486Smckusick 184443452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 184543452Shibler if (error == 0) 184643452Shibler *retval = p->p_nice - NZERO; 184744421Skarels return (error); 184841486Smckusick } 184941486Smckusick 185054917Storek struct ohpuxtimes_args { 185154917Storek struct tms *tmsb; 185254917Storek }; 185343452Shibler ohpuxtimes(p, uap, retval) 185443452Shibler struct proc *p; 185554917Storek register struct ohpuxtimes_args *uap; 185654917Storek int *retval; 185741486Smckusick { 185854771Storek struct timeval ru, rs; 185941486Smckusick struct tms atms; 186043452Shibler int error; 186141486Smckusick 186254771Storek calcru(p, &ru, &rs, NULL); 186354771Storek atms.tms_utime = hpuxscale(&ru); 186454771Storek atms.tms_stime = hpuxscale(&rs); 186548478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 186648478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 186743452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 186843452Shibler if (error == 0) 186954917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 187044421Skarels return (error); 187141486Smckusick } 187241486Smckusick 187345753Smckusick /* 187445753Smckusick * Doesn't exactly do what the documentation says. 187545753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 187645753Smckusick * is what HP-UX returns. 187745753Smckusick */ 187845753Smckusick hpuxscale(tvp) 187941486Smckusick register struct timeval *tvp; 188041486Smckusick { 188145753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 188241486Smckusick } 188341486Smckusick 188441486Smckusick /* 188541486Smckusick * Set IUPD and IACC times on file. 188641486Smckusick * Can't set ICHG. 188741486Smckusick */ 188854917Storek struct ohpuxutime_args { 188954917Storek char *fname; 189054917Storek time_t *tptr; 189154917Storek }; 189243452Shibler ohpuxutime(p, uap, retval) 189343452Shibler struct proc *p; 189454917Storek register struct ohpuxutime_args *uap; 189543452Shibler int *retval; 189643452Shibler { 189748478Skarels register struct vnode *vp; 189841486Smckusick struct vattr vattr; 189941486Smckusick time_t tv[2]; 190043452Shibler int error; 190148478Skarels struct nameidata nd; 190241486Smckusick 190341486Smckusick if (uap->tptr) { 190443452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 190543452Shibler if (error) 190644421Skarels return (error); 190741486Smckusick } else 190841486Smckusick tv[0] = tv[1] = time.tv_sec; 190941486Smckusick vattr_null(&vattr); 191054107Smckusick vattr.va_atime.ts_sec = tv[0]; 191154107Smckusick vattr.va_atime.ts_nsec = 0; 191254107Smckusick vattr.va_mtime.ts_sec = tv[1]; 191354107Smckusick vattr.va_mtime.ts_nsec = 0; 191452330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 191552330Smckusick if (error = namei(&nd)) 191644421Skarels return (error); 191752330Smckusick vp = nd.ni_vp; 191842154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 191943452Shibler error = EROFS; 192041486Smckusick else 192152330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 192241486Smckusick vput(vp); 192344421Skarels return (error); 192441486Smckusick } 192541486Smckusick 192643452Shibler ohpuxpause(p, uap, retval) 192743452Shibler struct proc *p; 192843452Shibler int *uap, *retval; 192941486Smckusick { 193049134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 193142155Skarels /* always return EINTR rather than ERESTART... */ 193244421Skarels return (EINTR); 193341486Smckusick } 193441486Smckusick 193541486Smckusick /* 193641486Smckusick * The old fstat system call. 193741486Smckusick */ 193854917Storek struct ohpuxfstat_args { 193954917Storek int fd; 194054917Storek struct ohpuxstat *sb; 194154917Storek }; 194243452Shibler ohpuxfstat(p, uap, retval) 194343452Shibler struct proc *p; 194454917Storek register struct ohpuxfstat_args *uap; 194543452Shibler int *retval; 194643452Shibler { 194745923Smckusick register struct filedesc *fdp = p->p_fd; 194841486Smckusick struct file *fp; 194941486Smckusick 195048478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 195148478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 195244421Skarels return (EBADF); 195343452Shibler if (fp->f_type != DTYPE_VNODE) 195444421Skarels return (EINVAL); 195555282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 195641486Smckusick } 195741486Smckusick 195841486Smckusick /* 195941486Smckusick * Old stat system call. This version follows links. 196041486Smckusick */ 196154917Storek struct ohpuxstat_args { 196254917Storek char *fname; 196354917Storek struct ohpuxstat *sb; 196454917Storek }; 196543452Shibler ohpuxstat(p, uap, retval) 196643452Shibler struct proc *p; 196754917Storek register struct ohpuxstat_args *uap; 196843452Shibler int *retval; 196943452Shibler { 197043452Shibler int error; 197148478Skarels struct nameidata nd; 197241486Smckusick 197352330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 197452330Smckusick if (error = namei(&nd)) 197544421Skarels return (error); 197655282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 197752330Smckusick vput(nd.ni_vp); 197844421Skarels return (error); 197941486Smckusick } 198041486Smckusick 198141486Smckusick int 198255282Smckusick ohpuxstat1(vp, ub, p) 1983*57307Shibler struct vnode *vp; 198441486Smckusick struct ohpuxstat *ub; 198555282Smckusick struct proc *p; 198641486Smckusick { 1987*57307Shibler struct ohpuxstat ohsb; 1988*57307Shibler struct stat sb; 1989*57307Shibler int error; 199041486Smckusick 1991*57307Shibler error = vn_stat(vp, &sb, p); 199241486Smckusick if (error) 1993*57307Shibler return (error); 1994*57307Shibler 1995*57307Shibler ohsb.ohst_dev = sb.st_dev; 1996*57307Shibler ohsb.ohst_ino = sb.st_ino; 1997*57307Shibler ohsb.ohst_mode = sb.st_mode; 1998*57307Shibler ohsb.ohst_nlink = sb.st_nlink; 1999*57307Shibler ohsb.ohst_uid = sb.st_uid; 2000*57307Shibler ohsb.ohst_gid = sb.st_gid; 2001*57307Shibler ohsb.ohst_rdev = sb.st_rdev; 2002*57307Shibler if (sb.st_size < (quad_t)1 << 32) 2003*57307Shibler ohsb.ohst_size = sb.st_size; 2004*57307Shibler else 2005*57307Shibler ohsb.ohst_size = -2; 2006*57307Shibler ohsb.ohst_atime = sb.st_atime; 2007*57307Shibler ohsb.ohst_mtime = sb.st_mtime; 2008*57307Shibler ohsb.ohst_ctime = sb.st_ctime; 2009*57307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 201041486Smckusick } 201141486Smckusick #endif 201255832Shibler #endif 2013