141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 3*63734Sbostic * Copyright (c) 1990, 1993 4*63734Sbostic * The Regents of the University of California. 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 * 1263726Shibler * from: Utah $Hdr: hpux_compat.c 1.59 93/06/15$ 1341486Smckusick * 14*63734Sbostic * @(#)hpux_compat.c 8.1 (Berkeley) 07/08/93 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1854857Shibler * Various HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2259982Smckusick #ifndef COMPAT_43 2359982Smckusick #define COMPAT_43 2459982Smckusick #endif 2541486Smckusick 2656506Sbostic #include <sys/param.h> 2756506Sbostic #include <sys/systm.h> 2856506Sbostic #include <sys/signalvar.h> 2956506Sbostic #include <sys/kernel.h> 3056506Sbostic #include <sys/filedesc.h> 3156506Sbostic #include <sys/proc.h> 3256506Sbostic #include <sys/buf.h> 3356506Sbostic #include <sys/wait.h> 3456506Sbostic #include <sys/file.h> 3556506Sbostic #include <sys/namei.h> 3656506Sbostic #include <sys/vnode.h> 3756506Sbostic #include <sys/ioctl.h> 3856506Sbostic #include <sys/ptrace.h> 3956506Sbostic #include <sys/stat.h> 4056506Sbostic #include <sys/syslog.h> 4156506Sbostic #include <sys/malloc.h> 4256506Sbostic #include <sys/mount.h> 4356506Sbostic #include <sys/ipc.h> 4456506Sbostic #include <sys/user.h> 4557307Shibler #include <sys/mman.h> 4641486Smckusick 4756506Sbostic #include <machine/cpu.h> 4856506Sbostic #include <machine/reg.h> 4956506Sbostic #include <machine/psl.h> 5056506Sbostic #include <machine/vmparam.h> 5156506Sbostic #include <hp/hpux/hpux.h> 5256506Sbostic #include <hp/hpux/hpux_termio.h> 5356506Sbostic 5441486Smckusick #ifdef DEBUG 5541486Smckusick int unimpresponse = 0; 5641486Smckusick #endif 5741486Smckusick 5841486Smckusick /* SYS5 style UTSNAME info */ 5941486Smckusick struct hpuxutsname protoutsname = { 6057307Shibler "4.4bsd", "", "0.5", "B", "9000/3?0", "" 6141486Smckusick }; 6241486Smckusick 6341486Smckusick /* 6.0 and later style context */ 6453922Shibler #if defined(HP380) 6553922Shibler char hpux040context[] = 6653922Shibler "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6753922Shibler #endif 6841486Smckusick #ifdef FPCOPROC 6941486Smckusick char hpuxcontext[] = 7041486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 7141486Smckusick #else 7241486Smckusick char hpuxcontext[] = 7341486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 7441486Smckusick #endif 7541486Smckusick 7641486Smckusick /* YP domainname */ 7741486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7841486Smckusick int domainnamelen = 7; 7941486Smckusick 8041486Smckusick #define NERR 79 8141486Smckusick #define BERR 1000 8241486Smckusick 8341486Smckusick /* indexed by BSD errno */ 8441486Smckusick short bsdtohpuxerrnomap[NERR] = { 8541486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8641486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8741486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8841486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8941486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 9041486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 9141486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 9241486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 9341486Smckusick }; 9441486Smckusick 9543452Shibler notimp(p, uap, retval, code, nargs) 9643452Shibler struct proc *p; 9743452Shibler int *uap, *retval; 9843452Shibler int code, nargs; 9941486Smckusick { 10043452Shibler int error = 0; 10141486Smckusick #ifdef DEBUG 10243452Shibler register int *argp = uap; 10341486Smckusick extern char *hpuxsyscallnames[]; 10441486Smckusick 10554857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10641486Smckusick if (nargs) 10741486Smckusick while (nargs--) 10841486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10941486Smckusick else 11041486Smckusick printf(")"); 11141486Smckusick printf("\n"); 11241486Smckusick switch (unimpresponse) { 11341486Smckusick case 0: 11443452Shibler error = nosys(p, uap, retval); 11541486Smckusick break; 11641486Smckusick case 1: 11743452Shibler error = EINVAL; 11841486Smckusick break; 11941486Smckusick } 12041486Smckusick #else 12143452Shibler error = nosys(p, uap, retval); 12241486Smckusick #endif 12343452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12444421Skarels return (error); 12541486Smckusick } 12641486Smckusick 12754917Storek struct hpuxexecv_args { 12854917Storek char *fname; 12954917Storek char **argp; 13054917Storek char **envp; 13154917Storek }; 13248478Skarels hpuxexecv(p, uap, retval) 13348478Skarels struct proc *p; 13454917Storek struct hpuxexecv_args *uap; 13548478Skarels int *retval; 13648478Skarels { 13748478Skarels extern int execve(); 13848478Skarels 13948478Skarels uap->envp = NULL; 14048478Skarels return (execve(p, uap, retval)); 14148478Skarels } 14248478Skarels 14341486Smckusick /* 14454857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 14541486Smckusick * (status pointer, options, rusage) into the kernel rather than 14642352Smckusick * handling it in the C library stub. We also need to map any 14754857Shibler * termination signal from BSD to HP-UX. 14841486Smckusick */ 14954917Storek struct hpuxwait3_args { 15054917Storek int *status; 15154917Storek int options; 15254917Storek int rusage; 15354917Storek }; 15443452Shibler hpuxwait3(p, uap, retval) 15543452Shibler struct proc *p; 15654917Storek struct hpuxwait3_args *uap; 15743452Shibler int *retval; 15843452Shibler { 15941486Smckusick /* rusage pointer must be zero */ 16043452Shibler if (uap->rusage) 16144421Skarels return (EINVAL); 16252381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 16352381Smckusick p->p_md.md_regs[R0] = uap->options; 16452381Smckusick p->p_md.md_regs[R1] = uap->rusage; 16544421Skarels return (hpuxwait(p, uap, retval)); 16641486Smckusick } 16741486Smckusick 16854917Storek struct hpuxwait_args { 16954917Storek int *status; 17054917Storek }; 17143452Shibler hpuxwait(p, uap, retval) 17243452Shibler struct proc *p; 17354917Storek struct hpuxwait_args *uap; 17443452Shibler int *retval; 17541486Smckusick { 17643452Shibler int sig, *statp, error; 17741486Smckusick 17841486Smckusick statp = uap->status; /* owait clobbers first arg */ 17943452Shibler error = owait(p, uap, retval); 18041486Smckusick /* 18141486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 18241486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 18341486Smckusick */ 18443452Shibler if (error == ERESTART) 18543452Shibler error = EINTR; 18643452Shibler if (error) 18744421Skarels return (error); 18843452Shibler sig = retval[1] & 0xFF; 18941486Smckusick if (sig == WSTOPPED) { 19043452Shibler sig = (retval[1] >> 8) & 0xFF; 19143452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 19241486Smckusick } else if (sig) 19343452Shibler retval[1] = (retval[1] & 0xFF00) | 19441486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 19541486Smckusick if (statp) 19643452Shibler if (suword((caddr_t)statp, retval[1])) 19743452Shibler error = EFAULT; 19844421Skarels return (error); 19941486Smckusick } 20041486Smckusick 20154917Storek struct hpuxwaitpid_args { 20254917Storek int pid; 20354917Storek int *status; 20454917Storek int options; 20554917Storek struct rusage *rusage; /* wait4 arg */ 20654917Storek }; 20743452Shibler hpuxwaitpid(p, uap, retval) 20843452Shibler struct proc *p; 20954917Storek struct hpuxwaitpid_args *uap; 21043452Shibler int *retval; 21143452Shibler { 21255832Shibler int rv, sig, xstat, error; 21342352Smckusick 21442352Smckusick uap->rusage = 0; 21543452Shibler error = wait4(p, uap, retval); 21642352Smckusick /* 21742352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21842352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21942352Smckusick */ 22043452Shibler if (error == ERESTART) 22143452Shibler error = EINTR; 22243452Shibler if (error) 22344421Skarels return (error); 22455832Shibler if (uap->status) { 22555832Shibler /* 22655832Shibler * Wait4 already wrote the status out to user space, 22755832Shibler * pull it back, change the signal portion, and write 22855832Shibler * it back out. 22955832Shibler */ 23055832Shibler rv = fuword((caddr_t)uap->status); 23155832Shibler if (WIFSTOPPED(rv)) { 23255832Shibler sig = WSTOPSIG(rv); 23355832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 23455832Shibler } else if (WIFSIGNALED(rv)) { 23555832Shibler sig = WTERMSIG(rv); 23655832Shibler xstat = WEXITSTATUS(rv); 23755832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 23855832Shibler WCOREDUMP(rv); 23955832Shibler } 24055832Shibler (void)suword((caddr_t)uap->status, rv); 24155832Shibler } 24244421Skarels return (error); 24342352Smckusick } 24442352Smckusick 24541486Smckusick /* 24663726Shibler * Old creat system call. 24763726Shibler */ 24863726Shibler struct hpuxcreat_args { 24963726Shibler char *fname; 25063726Shibler int fmode; 25163726Shibler }; 25263726Shibler hpuxcreat(p, uap, retval) 25363726Shibler struct proc *p; 25463726Shibler register struct hpuxcreat_args *uap; 25563726Shibler int *retval; 25663726Shibler { 25763726Shibler struct nargs { 25863726Shibler char *fname; 25963726Shibler int mode; 26063726Shibler int crtmode; 26163726Shibler } openuap; 26263726Shibler 26363726Shibler openuap.fname = uap->fname; 26463726Shibler openuap.crtmode = uap->fmode; 26563726Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 26663726Shibler return (open(p, &openuap, retval)); 26763726Shibler } 26863726Shibler 26963726Shibler /* 27063726Shibler * XXX extensions to the fd_ofileflags flags. 27163726Shibler * Hate to put this there, but they do need to be per-file. 27263726Shibler */ 27363726Shibler #define UF_NONBLOCK_ON 0x10 27463726Shibler #define UF_FNDELAY_ON 0x20 27563726Shibler #define UF_FIONBIO_ON 0x40 27663726Shibler 27763726Shibler /* 27841486Smckusick * Must remap some bits in the mode mask. 27941486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 28063726Shibler * O_NONBLOCK is remapped and remembered, 28163726Shibler * O_FNDELAY is remembered, 28263726Shibler * O_SYNCIO is removed entirely. 28341486Smckusick */ 28454917Storek struct hpuxopen_args { 28554917Storek char *fname; 28654917Storek int mode; 28754917Storek int crtmode; 28854917Storek }; 28943067Skarels hpuxopen(p, uap, retval) 29043067Skarels struct proc *p; 29154917Storek register struct hpuxopen_args *uap; 29243067Skarels int *retval; 29343067Skarels { 29463726Shibler int mode, error; 29541486Smckusick 29641486Smckusick mode = uap->mode; 29763726Shibler uap->mode &= 29863726Shibler ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 29941486Smckusick if (mode & HPUXFCREAT) { 30041486Smckusick /* 30141486Smckusick * simulate the pre-NFS behavior that opening a 30241486Smckusick * file for READ+CREATE ignores the CREATE (unless 30341486Smckusick * EXCL is set in which case we will return the 30441486Smckusick * proper error). 30541486Smckusick */ 30648478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 30749950Smckusick uap->mode |= O_CREAT; 30841486Smckusick } 30941486Smckusick if (mode & HPUXFTRUNC) 31049950Smckusick uap->mode |= O_TRUNC; 31141486Smckusick if (mode & HPUXFEXCL) 31249950Smckusick uap->mode |= O_EXCL; 31363726Shibler if (mode & HPUXNONBLOCK) 31463726Shibler uap->mode |= O_NDELAY; 31563726Shibler error = open(p, uap, retval); 31663726Shibler /* 31763726Shibler * Record non-blocking mode for fcntl, read, write, etc. 31863726Shibler */ 31963726Shibler if (error == 0 && (uap->mode & O_NDELAY)) 32063726Shibler p->p_fd->fd_ofileflags[*retval] |= 32163726Shibler (mode & HPUXNONBLOCK) ? UF_NONBLOCK_ON : UF_FNDELAY_ON; 32263726Shibler return (error); 32341486Smckusick } 32441486Smckusick 32554917Storek struct hpuxfcntl_args { 32654917Storek int fdes; 32754917Storek int cmd; 32854917Storek int arg; 32954917Storek }; 33043452Shibler hpuxfcntl(p, uap, retval) 33143452Shibler struct proc *p; 33254917Storek register struct hpuxfcntl_args *uap; 33343452Shibler int *retval; 33443452Shibler { 33543452Shibler int mode, error; 33649329Shibler char *fp; 33741486Smckusick 33849329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 33949329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 34049329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 34149329Shibler return (EBADF); 34249329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 34349329Shibler } 34441486Smckusick switch (uap->cmd) { 34541486Smckusick case F_SETFL: 34663726Shibler if (uap->arg & HPUXNONBLOCK) 34763726Shibler *fp |= UF_NONBLOCK_ON; 34863726Shibler else 34963726Shibler *fp &= ~UF_NONBLOCK_ON; 35049950Smckusick if (uap->arg & FNONBLOCK) 35149329Shibler *fp |= UF_FNDELAY_ON; 35263726Shibler else 35349329Shibler *fp &= ~UF_FNDELAY_ON; 35463726Shibler if (*fp & (UF_NONBLOCK_ON|UF_FNDELAY_ON|UF_FIONBIO_ON)) 35563726Shibler uap->arg |= FNONBLOCK; 35663726Shibler uap->arg &= ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFREMOTE); 35741486Smckusick break; 35841486Smckusick case F_GETFL: 35941486Smckusick case F_DUPFD: 36041486Smckusick case F_GETFD: 36141486Smckusick case F_SETFD: 36241486Smckusick break; 36341486Smckusick default: 36444421Skarels return (EINVAL); 36541486Smckusick } 36643452Shibler error = fcntl(p, uap, retval); 36749329Shibler if (error == 0 && uap->cmd == F_GETFL) { 36843452Shibler mode = *retval; 36963726Shibler *retval &= ~(O_CREAT|O_TRUNC|O_EXCL); 37063726Shibler if (mode & FNONBLOCK) { 37163726Shibler if (*fp & UF_NONBLOCK_ON) 37263726Shibler *retval |= HPUXNONBLOCK; 37363726Shibler if ((*fp & UF_FNDELAY_ON) == 0) 37463726Shibler *retval &= ~FNONBLOCK; 37563726Shibler } 37649950Smckusick if (mode & O_CREAT) 37743452Shibler *retval |= HPUXFCREAT; 37849950Smckusick if (mode & O_TRUNC) 37943452Shibler *retval |= HPUXFTRUNC; 38049950Smckusick if (mode & O_EXCL) 38143452Shibler *retval |= HPUXFEXCL; 38241486Smckusick } 38344421Skarels return (error); 38441486Smckusick } 38541486Smckusick 38641486Smckusick /* 38763726Shibler * Read and write calls. Same as BSD except for non-blocking behavior. 38863726Shibler * There are three types of non-blocking reads/writes in HP-UX checked 38963726Shibler * in the following order: 39049329Shibler * 39163726Shibler * O_NONBLOCK: return -1 and errno == EAGAIN 39263726Shibler * O_NDELAY: return 0 39363726Shibler * FIOSNBIO: return -1 and errno == EWOULDBLOCK 39441486Smckusick */ 39563726Shibler struct hpuxrw_args { 39663726Shibler int fd; 39754917Storek }; 39863726Shibler 39943452Shibler hpuxread(p, uap, retval) 40043452Shibler struct proc *p; 40163726Shibler struct hpuxrw_args *uap; 40243452Shibler int *retval; 40341486Smckusick { 40443452Shibler int error; 40541486Smckusick 40643452Shibler error = read(p, uap, retval); 40763726Shibler if (error == EWOULDBLOCK) { 40863726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 40963726Shibler 41063726Shibler if (*fp & UF_NONBLOCK_ON) { 41163726Shibler *retval = -1; 41263726Shibler error = EAGAIN; 41363726Shibler } else if (*fp & UF_FNDELAY_ON) { 41463726Shibler *retval = 0; 41563726Shibler error = 0; 41663726Shibler } 41741486Smckusick } 41844421Skarels return (error); 41941486Smckusick } 42041486Smckusick 42143452Shibler hpuxwrite(p, uap, retval) 42243452Shibler struct proc *p; 42363726Shibler struct hpuxrw_args *uap; 42443452Shibler int *retval; 42541486Smckusick { 42643452Shibler int error; 42741486Smckusick 42843452Shibler error = write(p, uap, retval); 42963726Shibler if (error == EWOULDBLOCK) { 43063726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 43163726Shibler 43263726Shibler if (*fp & UF_NONBLOCK_ON) { 43363726Shibler *retval = -1; 43463726Shibler error = EAGAIN; 43563726Shibler } else if (*fp & UF_FNDELAY_ON) { 43663726Shibler *retval = 0; 43763726Shibler error = 0; 43863726Shibler } 43941486Smckusick } 44044421Skarels return (error); 44141486Smckusick } 44241486Smckusick 44343452Shibler hpuxreadv(p, uap, retval) 44443452Shibler struct proc *p; 44563726Shibler struct hpuxrw_args *uap; 44643452Shibler int *retval; 44741486Smckusick { 44843452Shibler int error; 44941486Smckusick 45043452Shibler error = readv(p, uap, retval); 45163726Shibler if (error == EWOULDBLOCK) { 45263726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 45363726Shibler 45463726Shibler if (*fp & UF_NONBLOCK_ON) { 45563726Shibler *retval = -1; 45663726Shibler error = EAGAIN; 45763726Shibler } else if (*fp & UF_FNDELAY_ON) { 45863726Shibler *retval = 0; 45963726Shibler error = 0; 46063726Shibler } 46141486Smckusick } 46244421Skarels return (error); 46341486Smckusick } 46441486Smckusick 46543452Shibler hpuxwritev(p, uap, retval) 46643452Shibler struct proc *p; 46763726Shibler struct hpuxrw_args *uap; 46843452Shibler int *retval; 46941486Smckusick { 47043452Shibler int error; 47141486Smckusick 47243452Shibler error = writev(p, uap, retval); 47363726Shibler if (error == EWOULDBLOCK) { 47463726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 47563726Shibler 47663726Shibler if (*fp & UF_NONBLOCK_ON) { 47763726Shibler *retval = -1; 47863726Shibler error = EAGAIN; 47963726Shibler } else if (*fp & UF_FNDELAY_ON) { 48063726Shibler *retval = 0; 48163726Shibler error = 0; 48263726Shibler } 48341486Smckusick } 48444421Skarels return (error); 48541486Smckusick } 48641486Smckusick 48741486Smckusick /* 48841486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 48954857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 49041486Smckusick */ 49154917Storek struct hpuxdup_args { 49254917Storek int i; 49354917Storek }; 49443452Shibler hpuxdup(p, uap, retval) 49543452Shibler struct proc *p; 49654917Storek register struct hpuxdup_args *uap; 49743452Shibler int *retval; 49841486Smckusick { 49945923Smckusick register struct filedesc *fdp = p->p_fd; 50041486Smckusick struct file *fp; 50143452Shibler int fd, error; 50241486Smckusick 50348478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 50448478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 50544421Skarels return (EBADF); 50648478Skarels if (error = fdalloc(p, 0, &fd)) 50744421Skarels return (error); 50848478Skarels fdp->fd_ofiles[fd] = fp; 50948478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 51045923Smckusick fp->f_count++; 51145923Smckusick if (fd > fdp->fd_lastfile) 51245923Smckusick fdp->fd_lastfile = fd; 51343452Shibler *retval = fd; 51444421Skarels return (0); 51541486Smckusick } 51641486Smckusick 51754917Storek struct hpuxutssys_args { 51854917Storek struct hpuxutsname *uts; 51954917Storek int dev; 52054917Storek int request; 52154917Storek }; 52245753Smckusick hpuxutssys(p, uap, retval) 52343452Shibler struct proc *p; 52454917Storek register struct hpuxutssys_args *uap; 52543452Shibler int *retval; 52643452Shibler { 52741486Smckusick register int i; 52843452Shibler int error; 52941486Smckusick 53041486Smckusick switch (uap->request) { 53141486Smckusick /* uname */ 53241486Smckusick case 0: 53341486Smckusick /* fill in machine type */ 53441486Smckusick switch (machineid) { 53541486Smckusick case HP_320: 53641486Smckusick protoutsname.machine[6] = '2'; 53741486Smckusick break; 53841486Smckusick /* includes 318 and 319 */ 53941486Smckusick case HP_330: 54041486Smckusick protoutsname.machine[6] = '3'; 54141486Smckusick break; 54241486Smckusick case HP_340: 54341486Smckusick protoutsname.machine[6] = '4'; 54441486Smckusick break; 54541486Smckusick case HP_350: 54641486Smckusick protoutsname.machine[6] = '5'; 54741486Smckusick break; 54841486Smckusick case HP_360: 54941486Smckusick protoutsname.machine[6] = '6'; 55041486Smckusick break; 55141486Smckusick case HP_370: 55241486Smckusick protoutsname.machine[6] = '7'; 55341486Smckusick break; 55443452Shibler /* includes 345 */ 55543452Shibler case HP_375: 55643452Shibler protoutsname.machine[6] = '7'; 55743452Shibler protoutsname.machine[7] = '5'; 55843452Shibler break; 55954857Shibler /* includes 425 */ 56054857Shibler case HP_380: 56154857Shibler protoutsname.machine[6] = '8'; 56254857Shibler break; 56357307Shibler case HP_433: 56457307Shibler protoutsname.machine[5] = '4'; 56557307Shibler protoutsname.machine[6] = '3'; 56657307Shibler protoutsname.machine[7] = '3'; 56757307Shibler break; 56841486Smckusick } 56941486Smckusick /* copy hostname (sans domain) to nodename */ 57049329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 57141486Smckusick protoutsname.nodename[i] = hostname[i]; 57249329Shibler protoutsname.nodename[i] = '\0'; 57343452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 57443452Shibler sizeof(struct hpuxutsname)); 57541486Smckusick break; 57645753Smckusick 57745753Smckusick /* gethostname */ 57845753Smckusick case 5: 57945753Smckusick /* uap->dev is length */ 58045753Smckusick if (uap->dev > hostnamelen + 1) 58145753Smckusick uap->dev = hostnamelen + 1; 58245753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 58345753Smckusick uap->dev); 58445753Smckusick break; 58545753Smckusick 58645753Smckusick case 1: /* ?? */ 58745753Smckusick case 2: /* ustat */ 58845753Smckusick case 3: /* ?? */ 58945753Smckusick case 4: /* sethostname */ 59041486Smckusick default: 59143452Shibler error = EINVAL; 59241486Smckusick break; 59341486Smckusick } 59444421Skarels return (error); 59541486Smckusick } 59641486Smckusick 59754917Storek struct hpuxsysconf_args { 59854917Storek int name; 59954917Storek }; 60053922Shibler hpuxsysconf(p, uap, retval) 60153922Shibler struct proc *p; 60254917Storek struct hpuxsysconf_args *uap; 60353922Shibler int *retval; 60453922Shibler { 60553922Shibler switch (uap->name) { 60653922Shibler 60753922Shibler /* open files */ 60853922Shibler case HPUX_SYSCONF_OPENMAX: 60953922Shibler *retval = NOFILE; 61053922Shibler break; 61153922Shibler 61253922Shibler /* architecture */ 61353922Shibler case HPUX_SYSCONF_CPUTYPE: 61453922Shibler switch (machineid) { 61553922Shibler case HP_320: 61653922Shibler case HP_330: 61753922Shibler case HP_350: 61853922Shibler *retval = HPUX_SYSCONF_CPUM020; 61953922Shibler break; 62053922Shibler case HP_340: 62153922Shibler case HP_360: 62253922Shibler case HP_370: 62353922Shibler case HP_375: 62453922Shibler *retval = HPUX_SYSCONF_CPUM030; 62553922Shibler break; 62653922Shibler case HP_380: 62757307Shibler case HP_433: 62853922Shibler *retval = HPUX_SYSCONF_CPUM040; 62953922Shibler break; 63053922Shibler } 63153922Shibler break; 63253922Shibler default: 63354857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 63453922Shibler return (EINVAL); 63553922Shibler } 63653922Shibler return (0); 63753922Shibler } 63853922Shibler 63954917Storek struct hpuxstat_args { 64054917Storek char *fname; 64154917Storek struct hpuxstat *hsb; 64254917Storek }; 64343452Shibler hpuxstat(p, uap, retval) 64443452Shibler struct proc *p; 64554917Storek struct hpuxstat_args *uap; 64643452Shibler int *retval; 64743452Shibler { 64855282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 64941486Smckusick } 65041486Smckusick 65154917Storek struct hpuxlstat_args { 65254917Storek char *fname; 65354917Storek struct hpuxstat *hsb; 65454917Storek }; 65543452Shibler hpuxlstat(p, uap, retval) 65643452Shibler struct proc *p; 65754917Storek struct hpuxlstat_args *uap; 65843452Shibler int *retval; 65941486Smckusick { 66055282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 66141486Smckusick } 66241486Smckusick 66354917Storek struct hpuxfstat_args { 66454917Storek int fdes; 66554917Storek struct hpuxstat *hsb; 66654917Storek }; 66743452Shibler hpuxfstat(p, uap, retval) 66843452Shibler struct proc *p; 66954917Storek register struct hpuxfstat_args *uap; 67043452Shibler int *retval; 67141486Smckusick { 67245923Smckusick register struct filedesc *fdp = p->p_fd; 67341486Smckusick register struct file *fp; 67441486Smckusick struct stat sb; 67543452Shibler int error; 67641486Smckusick 67748478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 67848478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 67944421Skarels return (EBADF); 68043452Shibler 68141486Smckusick switch (fp->f_type) { 68241486Smckusick 68341486Smckusick case DTYPE_VNODE: 68455282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 68541486Smckusick break; 68641486Smckusick 68741486Smckusick case DTYPE_SOCKET: 68855282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 68941486Smckusick break; 69041486Smckusick 69141486Smckusick default: 69241486Smckusick panic("fstat"); 69341486Smckusick /*NOTREACHED*/ 69441486Smckusick } 69541486Smckusick /* is this right for sockets?? */ 69643452Shibler if (error == 0) 69743452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 69844421Skarels return (error); 69941486Smckusick } 70041486Smckusick 70154917Storek struct hpuxulimit_args { 70254917Storek int cmd; 70354917Storek long newlimit; 70454917Storek }; 70543452Shibler hpuxulimit(p, uap, retval) 70643452Shibler struct proc *p; 70754917Storek register struct hpuxulimit_args *uap; 70853481Smckusick long *retval; 70943452Shibler { 71041486Smckusick struct rlimit *limp; 71143452Shibler int error = 0; 71241486Smckusick 71348478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 71441486Smckusick switch (uap->cmd) { 71541486Smckusick case 2: 71641486Smckusick uap->newlimit *= 512; 71741486Smckusick if (uap->newlimit > limp->rlim_max && 71848478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 71941486Smckusick break; 72041486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 72141486Smckusick /* else fall into... */ 72241486Smckusick 72341486Smckusick case 1: 72445753Smckusick *retval = limp->rlim_max / 512; 72541486Smckusick break; 72641486Smckusick 72741486Smckusick case 3: 72848478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 72948478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 73041486Smckusick break; 73141486Smckusick 73241486Smckusick default: 73343452Shibler error = EINVAL; 73441486Smckusick break; 73541486Smckusick } 73644421Skarels return (error); 73741486Smckusick } 73841486Smckusick 73941486Smckusick /* 74041486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 74141486Smckusick * values -16 (high) thru -1 (low). 74241486Smckusick */ 74354917Storek struct hpuxrtprio_args { 74454917Storek int pid; 74554917Storek int prio; 74654917Storek }; 74743452Shibler hpuxrtprio(cp, uap, retval) 74843452Shibler struct proc *cp; 74954917Storek register struct hpuxrtprio_args *uap; 75043452Shibler int *retval; 75143452Shibler { 75241486Smckusick struct proc *p; 75343452Shibler int nice, error; 75441486Smckusick 75541486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 75643452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 75744421Skarels return (EINVAL); 75841486Smckusick if (uap->pid == 0) 75943452Shibler p = cp; 76043452Shibler else if ((p = pfind(uap->pid)) == 0) 76144421Skarels return (ESRCH); 76241486Smckusick nice = p->p_nice; 76341486Smckusick if (nice < NZERO) 76443452Shibler *retval = (nice + 16) << 3; 76541486Smckusick else 76643452Shibler *retval = RTPRIO_RTOFF; 76741486Smckusick switch (uap->prio) { 76841486Smckusick 76941486Smckusick case RTPRIO_NOCHG: 77044421Skarels return (0); 77141486Smckusick 77241486Smckusick case RTPRIO_RTOFF: 77341486Smckusick if (nice >= NZERO) 77444421Skarels return (0); 77541486Smckusick nice = NZERO; 77641486Smckusick break; 77741486Smckusick 77841486Smckusick default: 77941486Smckusick nice = (uap->prio >> 3) - 16; 78041486Smckusick break; 78141486Smckusick } 78243452Shibler error = donice(cp, p, nice); 78343452Shibler if (error == EACCES) 78443452Shibler error = EPERM; 78544421Skarels return (error); 78641486Smckusick } 78741486Smckusick 78854917Storek struct hpuxadvise_args { 78954917Storek int arg; 79054917Storek }; 79143452Shibler hpuxadvise(p, uap, retval) 79243452Shibler struct proc *p; 79354917Storek struct hpuxadvise_args *uap; 79443452Shibler int *retval; 79541486Smckusick { 79643452Shibler int error = 0; 79741486Smckusick 79841486Smckusick switch (uap->arg) { 79941486Smckusick case 0: 80057307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 80141486Smckusick break; 80241486Smckusick case 1: 80341486Smckusick ICIA(); 80441486Smckusick break; 80541486Smckusick case 2: 80641486Smckusick DCIA(); 80741486Smckusick break; 80841486Smckusick default: 80943452Shibler error = EINVAL; 81041486Smckusick break; 81141486Smckusick } 81244421Skarels return (error); 81341486Smckusick } 81441486Smckusick 81554917Storek struct hpuxptrace_args { 81654917Storek int req; 81754917Storek int pid; 81854917Storek int *addr; 81954917Storek int data; 82054917Storek }; 82143452Shibler hpuxptrace(p, uap, retval) 82243452Shibler struct proc *p; 82354917Storek struct hpuxptrace_args *uap; 82443452Shibler int *retval; 82543452Shibler { 82657307Shibler int error, isps = 0; 82757307Shibler struct proc *cp; 82841486Smckusick 82957307Shibler switch (uap->req) { 83057307Shibler /* map signal */ 83157307Shibler case PT_STEP: 83257307Shibler case PT_CONTINUE: 83341486Smckusick if (uap->data) { 83441486Smckusick uap->data = hpuxtobsdsig(uap->data); 83541486Smckusick if (uap->data == 0) 83641486Smckusick uap->data = NSIG; 83741486Smckusick } 83857307Shibler break; 83957307Shibler /* map u-area offset */ 84057307Shibler case PT_READ_U: 84157307Shibler case PT_WRITE_U: 84257307Shibler /* 84357307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 84457307Shibler * to be called in the child context (procxmt) but we 84557307Shibler * do it here in the parent context to avoid hacks in 84657307Shibler * the MI sys_process.c file. This works only because 84757307Shibler * we can access the child's md_regs pointer and it 84857307Shibler * has the correct value (the child has already trapped 84957307Shibler * into the kernel). 85057307Shibler */ 85157307Shibler if ((cp = pfind(uap->pid)) == 0) 85257307Shibler return (ESRCH); 85357307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 85457307Shibler 85557307Shibler /* 85657307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 85757307Shibler * to write PS actually contain the PS in the high word 85857307Shibler * and the high half of the PC (the following register) 85957307Shibler * in the low word. Move the PS value to where BSD 86057307Shibler * expects it. 86157307Shibler */ 86257307Shibler if (isps && uap->req == PT_WRITE_U) 86357307Shibler uap->data >>= 16; 86457307Shibler break; 86541486Smckusick } 86643452Shibler error = ptrace(p, uap, retval); 86757307Shibler /* 86857307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 86957307Shibler * Note that we do not return the high part of PC like HP-UX 87057307Shibler * would, but the HP-UX debuggers don't require it. 87157307Shibler */ 87257307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 87357307Shibler *retval <<= 16; 87444421Skarels return (error); 87541486Smckusick } 87641486Smckusick 87754917Storek struct hpuxgetdomainname_args { 87854917Storek char *domainname; 87954917Storek u_int len; 88054917Storek }; 88143452Shibler hpuxgetdomainname(p, uap, retval) 88243452Shibler struct proc *p; 88354917Storek register struct hpuxgetdomainname_args *uap; 88443452Shibler int *retval; 88543452Shibler { 88641486Smckusick if (uap->len > domainnamelen + 1) 88741486Smckusick uap->len = domainnamelen + 1; 88844421Skarels return (copyout(domainname, uap->domainname, uap->len)); 88941486Smckusick } 89041486Smckusick 89154917Storek struct hpuxsetdomainname_args { 89254917Storek char *domainname; 89354917Storek u_int len; 89454917Storek }; 89543452Shibler hpuxsetdomainname(p, uap, retval) 89643452Shibler struct proc *p; 89754917Storek register struct hpuxsetdomainname_args *uap; 89843452Shibler int *retval; 89943452Shibler { 90043452Shibler int error; 90141486Smckusick 90248478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 90344421Skarels return (error); 90443452Shibler if (uap->len > sizeof (domainname) - 1) 90544421Skarels return (EINVAL); 90641486Smckusick domainnamelen = uap->len; 90743452Shibler error = copyin(uap->domainname, domainname, uap->len); 90841486Smckusick domainname[domainnamelen] = 0; 90944421Skarels return (error); 91041486Smckusick } 91141486Smckusick 91241486Smckusick #ifdef SYSVSHM 91356506Sbostic #include <sys/shm.h> 91454857Shibler 91543452Shibler hpuxshmat(p, uap, retval) 91643452Shibler struct proc *p; 91743452Shibler int *uap, *retval; 91841486Smckusick { 91944421Skarels return (shmat(p, uap, retval)); 92041486Smckusick } 92141486Smckusick 92243452Shibler hpuxshmdt(p, uap, retval) 92343452Shibler struct proc *p; 92443452Shibler int *uap, *retval; 92541486Smckusick { 92644421Skarels return (shmdt(p, uap, retval)); 92741486Smckusick } 92841486Smckusick 92943452Shibler hpuxshmget(p, uap, retval) 93043452Shibler struct proc *p; 93143452Shibler int *uap, *retval; 93241486Smckusick { 93344421Skarels return (shmget(p, uap, retval)); 93441486Smckusick } 93554857Shibler 93654857Shibler /* 93754857Shibler * Handle HP-UX specific commands. 93854857Shibler */ 93954917Storek struct hpuxshmctl_args { 94054917Storek int shmid; 94154917Storek int cmd; 94254917Storek caddr_t buf; 94354917Storek }; 94454857Shibler hpuxshmctl(p, uap, retval) 94554857Shibler struct proc *p; 94654917Storek struct hpuxshmctl_args *uap; 94754857Shibler int *retval; 94854857Shibler { 94954857Shibler register struct shmid_ds *shp; 95054857Shibler register struct ucred *cred = p->p_ucred; 95154857Shibler int error; 95254857Shibler 95354857Shibler if (error = shmvalid(uap->shmid)) 95454857Shibler return (error); 95554857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 95654857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 95754857Shibler /* don't really do anything, but make them think we did */ 95854857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 95954857Shibler cred->cr_uid != shp->shm_perm.cuid) 96054857Shibler return (EPERM); 96154857Shibler return (0); 96254857Shibler } 96354857Shibler return (shmctl(p, uap, retval)); 96454857Shibler } 96541486Smckusick #endif 96641486Smckusick 96741486Smckusick /* 96841486Smckusick * Fake semaphore routines, just don't return an error. 96941486Smckusick * Should be adequate for starbase to run. 97041486Smckusick */ 97154917Storek struct hpuxsemctl_args { 97254917Storek int semid; 97354917Storek u_int semnum; 97454917Storek int cmd; 97554917Storek int arg; 97654917Storek }; 97743452Shibler hpuxsemctl(p, uap, retval) 97843452Shibler struct proc *p; 97954917Storek struct hpuxsemctl_args *uap; 98043452Shibler int *retval; 98143452Shibler { 98241486Smckusick /* XXX: should do something here */ 98344421Skarels return (0); 98441486Smckusick } 98541486Smckusick 98654917Storek struct hpuxsemget_args { 98754917Storek key_t key; 98854917Storek int nsems; 98954917Storek int semflg; 99054917Storek }; 99143452Shibler hpuxsemget(p, uap, retval) 99243452Shibler struct proc *p; 99354917Storek struct hpuxsemget_args *uap; 99443452Shibler int *retval; 99543452Shibler { 99641486Smckusick /* XXX: should do something here */ 99744421Skarels return (0); 99841486Smckusick } 99941486Smckusick 100054917Storek struct hpuxsemop_args { 100154917Storek int semid; 100254917Storek struct sembuf *sops; 100354917Storek u_int nsops; 100454917Storek }; 100543452Shibler hpuxsemop(p, uap, retval) 100643452Shibler struct proc *p; 100754917Storek struct hpuxsemop_args *uap; 100843452Shibler int *retval; 100943452Shibler { 101041486Smckusick /* XXX: should do something here */ 101144421Skarels return (0); 101241486Smckusick } 101341486Smckusick 101457307Shibler /* 101557307Shibler * HP-UX mmap() emulation (mainly for shared library support). 101657307Shibler */ 101757307Shibler struct hpuxmmap_args { 101857307Shibler caddr_t addr; 101957307Shibler int len; 102057307Shibler int prot; 102157307Shibler int flags; 102257307Shibler int fd; 102357307Shibler long pos; 102457307Shibler }; 102557307Shibler hpuxmmap(p, uap, retval) 102657307Shibler struct proc *p; 102757307Shibler struct hpuxmmap_args *uap; 102857307Shibler int *retval; 102957307Shibler { 103057307Shibler struct mmap_args { 103157307Shibler caddr_t addr; 103257307Shibler int len; 103357307Shibler int prot; 103457307Shibler int flags; 103557307Shibler int fd; 103657307Shibler long pad; 103757307Shibler off_t pos; 103857307Shibler } nargs; 103957307Shibler 104057307Shibler nargs.addr = uap->addr; 104157307Shibler nargs.len = uap->len; 104257307Shibler nargs.prot = uap->prot; 104357307Shibler nargs.flags = uap->flags & 104457307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 104557307Shibler if (uap->flags & HPUXMAP_FIXED) 104657307Shibler nargs.flags |= MAP_FIXED; 104757307Shibler if (uap->flags & HPUXMAP_ANON) 104857307Shibler nargs.flags |= MAP_ANON; 104957307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 105057307Shibler nargs.pos = uap->pos; 105163440Sbostic return (mmap(p, &nargs, retval)); 105257307Shibler } 105357307Shibler 105454857Shibler /* convert from BSD to HP-UX errno */ 105541486Smckusick bsdtohpuxerrno(err) 105641486Smckusick int err; 105741486Smckusick { 105841486Smckusick if (err < 0 || err >= NERR) 105941486Smckusick return(BERR); 106041486Smckusick return((int)bsdtohpuxerrnomap[err]); 106141486Smckusick } 106241486Smckusick 106355282Smckusick hpuxstat1(fname, hsb, follow, p) 106441486Smckusick char *fname; 106541486Smckusick struct hpuxstat *hsb; 106641486Smckusick int follow; 106755282Smckusick struct proc *p; 106841486Smckusick { 106948478Skarels int error; 107041486Smckusick struct stat sb; 107148478Skarels struct nameidata nd; 107241486Smckusick 107355282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 107452330Smckusick if (error = namei(&nd)) 107541486Smckusick return (error); 107655282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 107752330Smckusick vput(nd.ni_vp); 107841486Smckusick if (error == 0) 107941486Smckusick error = bsdtohpuxstat(&sb, hsb); 108041486Smckusick return (error); 108141486Smckusick } 108241486Smckusick 108341486Smckusick #include "grf.h" 108453922Shibler #if NGRF > 0 108553922Shibler #ifdef __STDC__ 108653922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 108753922Shibler #else 108853922Shibler extern int grfopen(); 108953922Shibler #endif 109053922Shibler #endif 109141486Smckusick 109253922Shibler #define NHIL 1 /* XXX */ 109353922Shibler #if NHIL > 0 109453922Shibler #ifdef __STDC__ 109553922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 109653922Shibler #else 109753922Shibler extern int hilopen(); 109853922Shibler #endif 109953922Shibler #endif 110053922Shibler 110156506Sbostic #include <sys/conf.h> 110253922Shibler 110341486Smckusick bsdtohpuxstat(sb, hsb) 110441486Smckusick struct stat *sb; 110541486Smckusick struct hpuxstat *hsb; 110641486Smckusick { 110741486Smckusick struct hpuxstat ds; 110841486Smckusick 110941486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 111053481Smckusick ds.hst_dev = (u_short)sb->st_dev; 111141486Smckusick ds.hst_ino = (u_long)sb->st_ino; 111241486Smckusick ds.hst_mode = sb->st_mode; 111341486Smckusick ds.hst_nlink = sb->st_nlink; 111441486Smckusick ds.hst_uid = (u_short)sb->st_uid; 111541486Smckusick ds.hst_gid = (u_short)sb->st_gid; 111657307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 111757307Shibler 111853922Shibler /* XXX: I don't want to talk about it... */ 111953922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 112041486Smckusick #if NGRF > 0 112153922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 112253922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 112341486Smckusick #endif 112453922Shibler #if NHIL > 0 112553922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 112653922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 112753922Shibler #endif 112853922Shibler ; 112957307Shibler } 113053481Smckusick if (sb->st_size < (quad_t)1 << 32) 113153481Smckusick ds.hst_size = (long)sb->st_size; 113253481Smckusick else 113353481Smckusick ds.hst_size = -2; 113441486Smckusick ds.hst_atime = sb->st_atime; 113541486Smckusick ds.hst_mtime = sb->st_mtime; 113641486Smckusick ds.hst_ctime = sb->st_ctime; 113741486Smckusick ds.hst_blksize = sb->st_blksize; 113841486Smckusick ds.hst_blocks = sb->st_blocks; 113941486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 114041486Smckusick } 114141486Smckusick 114241486Smckusick hpuxtobsdioctl(com) 114341486Smckusick int com; 114441486Smckusick { 114541486Smckusick switch (com) { 114641486Smckusick case HPUXTIOCSLTC: 114741486Smckusick com = TIOCSLTC; break; 114841486Smckusick case HPUXTIOCGLTC: 114941486Smckusick com = TIOCGLTC; break; 115041486Smckusick case HPUXTIOCSPGRP: 115141486Smckusick com = TIOCSPGRP; break; 115241486Smckusick case HPUXTIOCGPGRP: 115341486Smckusick com = TIOCGPGRP; break; 115441486Smckusick case HPUXTIOCLBIS: 115541486Smckusick com = TIOCLBIS; break; 115641486Smckusick case HPUXTIOCLBIC: 115741486Smckusick com = TIOCLBIC; break; 115841486Smckusick case HPUXTIOCLSET: 115941486Smckusick com = TIOCLSET; break; 116041486Smckusick case HPUXTIOCLGET: 116141486Smckusick com = TIOCLGET; break; 116241486Smckusick } 116341486Smckusick return(com); 116441486Smckusick } 116541486Smckusick 116641486Smckusick /* 116754857Shibler * HP-UX ioctl system call. The differences here are: 116841486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 116949329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 117041486Smckusick * the sgttyb struct is 2 bytes longer 117141486Smckusick */ 117254917Storek struct hpuxioctl_args { 117354917Storek int fdes; 117454917Storek int cmd; 117554917Storek caddr_t cmarg; 117654917Storek }; 117743452Shibler hpuxioctl(p, uap, retval) 117843452Shibler struct proc *p; 117954917Storek register struct hpuxioctl_args *uap; 118043452Shibler int *retval; 118143452Shibler { 118245923Smckusick register struct filedesc *fdp = p->p_fd; 118343452Shibler register struct file *fp; 118443452Shibler register int com, error; 118541486Smckusick register u_int size; 118641486Smckusick caddr_t memp = 0; 118741486Smckusick #define STK_PARAMS 128 118841486Smckusick char stkbuf[STK_PARAMS]; 118941486Smckusick caddr_t data = stkbuf; 119041486Smckusick 119141486Smckusick com = uap->cmd; 119241486Smckusick 119341486Smckusick /* XXX */ 119443452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 119545923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 119641486Smckusick 119748478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 119848478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 119944421Skarels return (EBADF); 120043452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 120144421Skarels return (EBADF); 120241486Smckusick 120341486Smckusick /* 120441486Smckusick * Interpret high order word to find 120541486Smckusick * amount of data to be copied to/from the 120641486Smckusick * user's address space. 120741486Smckusick */ 120841486Smckusick size = IOCPARM_LEN(com); 120943452Shibler if (size > IOCPARM_MAX) 121044421Skarels return (ENOTTY); 121141486Smckusick if (size > sizeof (stkbuf)) { 121243452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 121341486Smckusick data = memp; 121441486Smckusick } 121541486Smckusick if (com&IOC_IN) { 121641486Smckusick if (size) { 121743452Shibler error = copyin(uap->cmarg, data, (u_int)size); 121843452Shibler if (error) { 121941486Smckusick if (memp) 122041486Smckusick free(memp, M_IOCTLOPS); 122144421Skarels return (error); 122241486Smckusick } 122341486Smckusick } else 122441486Smckusick *(caddr_t *)data = uap->cmarg; 122541486Smckusick } else if ((com&IOC_OUT) && size) 122641486Smckusick /* 122743452Shibler * Zero the buffer so the user always 122843452Shibler * gets back something deterministic. 122941486Smckusick */ 123041486Smckusick bzero(data, size); 123141486Smckusick else if (com&IOC_VOID) 123241486Smckusick *(caddr_t *)data = uap->cmarg; 123341486Smckusick 123441486Smckusick switch (com) { 123541486Smckusick 123649329Shibler case HPUXFIOSNBIO: 123749329Shibler { 123849329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 123949329Shibler int tmp; 124049329Shibler 124149329Shibler if (*(int *)data) 124249329Shibler *ofp |= UF_FIONBIO_ON; 124349329Shibler else 124449329Shibler *ofp &= ~UF_FIONBIO_ON; 124549329Shibler /* 124663726Shibler * Only set/clear if O_NONBLOCK/FNDELAY not in effect 124749329Shibler */ 124863726Shibler if ((*ofp & (UF_NONBLOCK_ON|UF_FNDELAY_ON)) == 0) { 124963726Shibler tmp = *ofp & UF_FIONBIO_ON; 125049329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 125149329Shibler (caddr_t)&tmp, p); 125249329Shibler } 125349329Shibler break; 125449329Shibler } 125549329Shibler 125641486Smckusick case HPUXTIOCCONS: 125741486Smckusick *(int *)data = 1; 125848478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 125941486Smckusick break; 126041486Smckusick 126141486Smckusick /* BSD-style job control ioctls */ 126241486Smckusick case HPUXTIOCLBIS: 126341486Smckusick case HPUXTIOCLBIC: 126441486Smckusick case HPUXTIOCLSET: 126541486Smckusick *(int *)data &= HPUXLTOSTOP; 126641486Smckusick if (*(int *)data & HPUXLTOSTOP) 126741486Smckusick *(int *)data = LTOSTOP; 126841486Smckusick /* fall into */ 126941486Smckusick case HPUXTIOCLGET: 127041486Smckusick case HPUXTIOCSLTC: 127141486Smckusick case HPUXTIOCGLTC: 127241486Smckusick case HPUXTIOCSPGRP: 127341486Smckusick case HPUXTIOCGPGRP: 127448478Skarels error = (*fp->f_ops->fo_ioctl) 127548478Skarels (fp, hpuxtobsdioctl(com), data, p); 127643452Shibler if (error == 0 && com == HPUXTIOCLGET) { 127741486Smckusick *(int *)data &= LTOSTOP; 127841486Smckusick if (*(int *)data & LTOSTOP) 127941486Smckusick *(int *)data = HPUXLTOSTOP; 128041486Smckusick } 128141486Smckusick break; 128241486Smckusick 128355832Shibler /* SYS 5 termio and POSIX termios */ 128441486Smckusick case HPUXTCGETA: 128541486Smckusick case HPUXTCSETA: 128641486Smckusick case HPUXTCSETAW: 128741486Smckusick case HPUXTCSETAF: 128855832Shibler case HPUXTCGETATTR: 128955832Shibler case HPUXTCSETATTR: 129055832Shibler case HPUXTCSETATTRD: 129155832Shibler case HPUXTCSETATTRF: 129248478Skarels error = hpuxtermio(fp, com, data, p); 129341486Smckusick break; 129441486Smckusick 129541486Smckusick default: 129648478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 129741486Smckusick break; 129841486Smckusick } 129941486Smckusick /* 130041486Smckusick * Copy any data to user, size was 130141486Smckusick * already set and checked above. 130241486Smckusick */ 130343452Shibler if (error == 0 && (com&IOC_OUT) && size) 130443452Shibler error = copyout(data, uap->cmarg, (u_int)size); 130541486Smckusick if (memp) 130641486Smckusick free(memp, M_IOCTLOPS); 130744421Skarels return (error); 130841486Smckusick } 130941486Smckusick 131041486Smckusick /* 131141486Smckusick * Man page lies, behaviour here is based on observed behaviour. 131241486Smckusick */ 131354917Storek struct hpuxgetcontext_args { 131454917Storek char *buf; 131554917Storek int len; 131654917Storek }; 131743452Shibler hpuxgetcontext(p, uap, retval) 131843452Shibler struct proc *p; 131954917Storek struct hpuxgetcontext_args *uap; 132043452Shibler int *retval; 132143452Shibler { 132241486Smckusick int error = 0; 132341486Smckusick register int len; 132441486Smckusick 132553922Shibler #if defined(HP380) 132653922Shibler if (machineid == HP_380) { 132755072Spendry len = min(uap->len, sizeof(hpux040context)); 132853922Shibler if (len) 132953922Shibler error = copyout(hpux040context, uap->buf, len); 133053922Shibler if (error == 0) 133153922Shibler *retval = sizeof(hpux040context); 133253922Shibler return (error); 133353922Shibler } 133453922Shibler #endif 133555072Spendry len = min(uap->len, sizeof(hpuxcontext)); 133641486Smckusick if (len) 133741486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 133843452Shibler if (error == 0) 133943452Shibler *retval = sizeof(hpuxcontext); 134044421Skarels return (error); 134141486Smckusick } 134241486Smckusick 134341486Smckusick /* 134441486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 134541486Smckusick * Note we do not check the real uid or "saved" uid. 134641486Smckusick */ 134754917Storek struct hpuxgetpgrp2_args { 134854917Storek int pid; 134954917Storek }; 135043452Shibler hpuxgetpgrp2(cp, uap, retval) 135143452Shibler struct proc *cp; 135254917Storek register struct hpuxgetpgrp2_args *uap; 135343452Shibler int *retval; 135441486Smckusick { 135541486Smckusick register struct proc *p; 135641486Smckusick 135741486Smckusick if (uap->pid == 0) 135843452Shibler uap->pid = cp->p_pid; 135941486Smckusick p = pfind(uap->pid); 136043452Shibler if (p == 0) 136144421Skarels return (ESRCH); 136248478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 136348478Skarels !inferior(p)) 136444421Skarels return (EPERM); 136543452Shibler *retval = p->p_pgid; 136644421Skarels return (0); 136741486Smckusick } 136841486Smckusick 136941486Smckusick /* 137041486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 137141486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 137241486Smckusick */ 137354917Storek struct hpuxsetpgrp2_args { 137454917Storek int pid; 137554917Storek int pgrp; 137654917Storek }; 137743452Shibler hpuxsetpgrp2(p, uap, retval) 137843452Shibler struct proc *p; 137954917Storek struct hpuxsetpgrp2_args *uap; 138043452Shibler int *retval; 138143452Shibler { 138241486Smckusick /* empirically determined */ 138343452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 138444421Skarels return (EINVAL); 138548478Skarels return (setpgid(p, uap, retval)); 138641486Smckusick } 138741486Smckusick 138841486Smckusick /* 138955165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 139045753Smckusick */ 139154917Storek struct hpuxsetresuid_args { 139254917Storek int ruid; 139354917Storek int euid; 139454917Storek int suid; 139554917Storek }; 139645753Smckusick hpuxsetresuid(p, uap, retval) 139755165Smckusick struct proc *p; 139854917Storek struct hpuxsetresuid_args *uap; 139945753Smckusick int *retval; 140045753Smckusick { 140155165Smckusick return (osetreuid(p, uap, retval)); 140245753Smckusick } 140345753Smckusick 140454917Storek struct hpuxsetresgid_args { 140554917Storek int rgid; 140654917Storek int egid; 140754917Storek int sgid; 140854917Storek }; 140945753Smckusick hpuxsetresgid(p, uap, retval) 141055165Smckusick struct proc *p; 141154917Storek struct hpuxsetresgid_args *uap; 141245753Smckusick int *retval; 141345753Smckusick { 141455165Smckusick return (osetregid(p, uap, retval)); 141545753Smckusick } 141645753Smckusick 141757307Shibler struct hpuxrlimit_args { 141857307Shibler u_int which; 141957307Shibler struct orlimit *rlp; 142057307Shibler }; 142157307Shibler hpuxgetrlimit(p, uap, retval) 142257307Shibler struct proc *p; 142357307Shibler struct hpuxrlimit_args *uap; 142457307Shibler int *retval; 142557307Shibler { 142657307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 142757307Shibler return (EINVAL); 142857307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 142957307Shibler uap->which = RLIMIT_NOFILE; 143060110Smckusick return (ogetrlimit(p, uap, retval)); 143157307Shibler } 143257307Shibler 143357307Shibler hpuxsetrlimit(p, uap, retval) 143457307Shibler struct proc *p; 143557307Shibler struct hpuxrlimit_args *uap; 143657307Shibler int *retval; 143757307Shibler { 143857307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 143957307Shibler return (EINVAL); 144057307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 144157307Shibler uap->which = RLIMIT_NOFILE; 144260110Smckusick return (osetrlimit(p, uap, retval)); 144357307Shibler } 144457307Shibler 144545753Smckusick /* 144645753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 144745753Smckusick */ 144854917Storek struct hpuxlockf_args { 144954917Storek int fd; 145054917Storek int func; 145154917Storek long size; 145254917Storek }; 145345753Smckusick hpuxlockf(p, uap, retval) 145445753Smckusick struct proc *p; 145554917Storek struct hpuxlockf_args *uap; 145645753Smckusick int *retval; 145745753Smckusick { 145845753Smckusick return (0); 145945753Smckusick } 146045753Smckusick 146154917Storek struct hpuxgetaccess_args { 146254917Storek char *path; 146354917Storek int uid; 146454917Storek int ngroups; 146554917Storek int *gidset; 146654917Storek void *label; 146754917Storek void *privs; 146854917Storek }; 146945753Smckusick hpuxgetaccess(p, uap, retval) 147045753Smckusick register struct proc *p; 147154917Storek register struct hpuxgetaccess_args *uap; 147245753Smckusick int *retval; 147345753Smckusick { 147445753Smckusick int lgroups[NGROUPS]; 147545753Smckusick int error = 0; 147645753Smckusick register struct ucred *cred; 147745753Smckusick register struct vnode *vp; 147852330Smckusick struct nameidata nd; 147945753Smckusick 148045753Smckusick /* 148145753Smckusick * Build an appropriate credential structure 148245753Smckusick */ 148348478Skarels cred = crdup(p->p_ucred); 148445753Smckusick switch (uap->uid) { 148545753Smckusick case 65502: /* UID_EUID */ 148645753Smckusick break; 148745753Smckusick case 65503: /* UID_RUID */ 148848478Skarels cred->cr_uid = p->p_cred->p_ruid; 148945753Smckusick break; 149045753Smckusick case 65504: /* UID_SUID */ 149145753Smckusick error = EINVAL; 149245753Smckusick break; 149345753Smckusick default: 149445753Smckusick if (uap->uid > 65504) 149545753Smckusick error = EINVAL; 149645753Smckusick cred->cr_uid = uap->uid; 149745753Smckusick break; 149845753Smckusick } 149945753Smckusick switch (uap->ngroups) { 150045753Smckusick case -1: /* NGROUPS_EGID */ 150145753Smckusick cred->cr_ngroups = 1; 150245753Smckusick break; 150345753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 150445753Smckusick break; 150545753Smckusick case -2: /* NGROUPS_RGID */ 150645753Smckusick cred->cr_ngroups = 1; 150748478Skarels cred->cr_gid = p->p_cred->p_rgid; 150845753Smckusick break; 150945753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 151048478Skarels cred->cr_gid = p->p_cred->p_rgid; 151145753Smckusick break; 151245753Smckusick case -3: /* NGROUPS_SGID */ 151345753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 151445753Smckusick error = EINVAL; 151545753Smckusick break; 151645753Smckusick case -4: /* NGROUPS_SUPP */ 151745753Smckusick if (cred->cr_ngroups > 1) 151845753Smckusick cred->cr_gid = cred->cr_groups[1]; 151945753Smckusick else 152045753Smckusick error = EINVAL; 152145753Smckusick break; 152245753Smckusick default: 152345753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 152445753Smckusick error = copyin((caddr_t)uap->gidset, 152545753Smckusick (caddr_t)&lgroups[0], 152645753Smckusick uap->ngroups * sizeof(lgroups[0])); 152745753Smckusick else 152845753Smckusick error = EINVAL; 152945753Smckusick if (error == 0) { 153045753Smckusick int gid; 153145753Smckusick 153245753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 153345753Smckusick cred->cr_groups[gid] = lgroups[gid]; 153445753Smckusick cred->cr_ngroups = uap->ngroups; 153545753Smckusick } 153645753Smckusick break; 153745753Smckusick } 153845753Smckusick /* 153945753Smckusick * Lookup file using caller's effective IDs. 154045753Smckusick */ 154145753Smckusick if (error == 0) { 154252330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 154352330Smckusick uap->path, p); 154452330Smckusick error = namei(&nd); 154545753Smckusick } 154645753Smckusick if (error) { 154745753Smckusick crfree(cred); 154845753Smckusick return (error); 154945753Smckusick } 155045753Smckusick /* 155145753Smckusick * Use the constructed credentials for access checks. 155245753Smckusick */ 155352330Smckusick vp = nd.ni_vp; 155445753Smckusick *retval = 0; 155548478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 155645753Smckusick *retval |= R_OK; 155748478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 155845753Smckusick *retval |= W_OK; 155945753Smckusick /* XXX we return X_OK for root on VREG even if not */ 156048478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 156145753Smckusick *retval |= X_OK; 156245753Smckusick vput(vp); 156345753Smckusick crfree(cred); 156445753Smckusick return (error); 156545753Smckusick } 156645753Smckusick 156749134Skarels extern char kstack[]; 156841486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 156941486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 157041486Smckusick 157141486Smckusick /* simplified FP structure */ 157241486Smckusick struct bsdfp { 157341486Smckusick int save[54]; 157441486Smckusick int reg[24]; 157541486Smckusick int ctrl[3]; 157641486Smckusick }; 157741486Smckusick 157857307Shibler /* 157957307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 158057307Shibler */ 158157307Shibler hpuxtobsduoff(off, isps, p) 158257307Shibler int *off, *isps; 158357307Shibler struct proc *p; 158441486Smckusick { 158557307Shibler register int *ar0 = p->p_md.md_regs; 158641486Smckusick struct hpuxfp *hp; 158741486Smckusick struct bsdfp *bp; 158841486Smckusick register u_int raddr; 158941486Smckusick 159057307Shibler *isps = 0; 159157307Shibler 159248478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 159341486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 159448478Skarels return(UOFF(U_ar0)); 159541486Smckusick 159641486Smckusick #ifdef FPCOPROC 159757307Shibler /* FP registers from PCB */ 159841486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 159941486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 160041486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 160141486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 160241486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 160341486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 160441486Smckusick #endif 160541486Smckusick 160641486Smckusick /* 160741486Smckusick * Everything else we recognize comes from the kernel stack, 160841486Smckusick * so we convert off to an absolute address (if not already) 160941486Smckusick * for simplicity. 161041486Smckusick */ 161141486Smckusick if (off < (int *)ctob(UPAGES)) 161249134Skarels off = (int *)((u_int)off + (u_int)kstack); 161341486Smckusick 161441486Smckusick /* 161557307Shibler * General registers. 161654857Shibler * We know that the HP-UX registers are in the same order as ours. 161741486Smckusick * The only difference is that their PS is 2 bytes instead of a 161841486Smckusick * padded 4 like ours throwing the alignment off. 161941486Smckusick */ 162048478Skarels if (off >= ar0 && off < &ar0[18]) { 162141486Smckusick /* 162241486Smckusick * PS: return low word and high word of PC as HP-UX would 162341486Smckusick * (e.g. &u.u_ar0[16.5]). 162457307Shibler * 162557307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 162657307Shibler * it and passing such an offset to procxmt will cause 162757307Shibler * it to fail anyway. Instead, we just set the offset 162857307Shibler * to PS and let hpuxptrace() shift up the value returned. 162941486Smckusick */ 163057307Shibler if (off == &ar0[PS]) { 163157307Shibler #if 0 163248478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 163357307Shibler #else 163457307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 163557307Shibler #endif 163657307Shibler *isps = 1; 163757307Shibler } 163841486Smckusick /* 163957307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 164057307Shibler * is only 16 bits. 164141486Smckusick */ 164248478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 164348478Skarels raddr = (u_int) &ar0[PC]; 164441486Smckusick /* 164541486Smckusick * D0-D7, A0-A7: easy 164641486Smckusick */ 164741486Smckusick else 164848478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 164949134Skarels return((int)(raddr - (u_int)kstack)); 165041486Smckusick } 165141486Smckusick 165241486Smckusick /* everything else */ 165341486Smckusick return(-1); 165441486Smckusick } 165541486Smckusick 165641486Smckusick /* 165754857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 165841486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 165941486Smckusick * convert the entire user struct. 166041486Smckusick */ 166141486Smckusick hpuxdumpu(vp, cred) 166241486Smckusick struct vnode *vp; 166341486Smckusick struct ucred *cred; 166441486Smckusick { 166548478Skarels struct proc *p = curproc; 166641486Smckusick int error; 166741486Smckusick struct hpuxuser *faku; 166841486Smckusick struct bsdfp *bp; 166941486Smckusick short *foop; 167041486Smckusick 167141486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 167241486Smckusick /* 167341486Smckusick * Make sure there is no mistake about this 167441486Smckusick * being a real user structure. 167541486Smckusick */ 167641486Smckusick bzero((caddr_t)faku, ctob(1)); 167741486Smckusick /* 167841486Smckusick * Fill in the process sizes. 167941486Smckusick */ 168048478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 168148478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 168248478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 168341486Smckusick /* 168441486Smckusick * Fill in the exec header for CDB. 168541486Smckusick * This was saved back in exec(). As far as I can tell CDB 168641486Smckusick * only uses this information to verify that a particular 168741486Smckusick * core file goes with a particular binary. 168841486Smckusick */ 168957307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 169041486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 169141486Smckusick /* 169241486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 169354857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 169441486Smckusick * so we have to move it up. 169541486Smckusick */ 169652381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 169752381Smckusick foop = (short *) p->p_md.md_regs; 169841486Smckusick foop[32] = foop[33]; 169941486Smckusick foop[33] = foop[34]; 170041486Smckusick foop[34] = foop[35]; 170141486Smckusick #ifdef FPCOPROC 170241486Smckusick /* 170354857Shibler * Copy 68881 registers from our PCB format to HP-UX format 170441486Smckusick */ 170549134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 170641486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 170741486Smckusick sizeof(bp->save)); 170841486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 170941486Smckusick sizeof(bp->ctrl)); 171041486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 171141486Smckusick sizeof(bp->reg)); 171241486Smckusick #endif 171341486Smckusick /* 171441486Smckusick * Slay the dragon 171541486Smckusick */ 171641486Smckusick faku->hpuxu_dragon = -1; 171741486Smckusick /* 171841486Smckusick * Dump this artfully constructed page in place of the 171941486Smckusick * user struct page. 172041486Smckusick */ 172148478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 172248478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 172349134Skarels (int *)NULL, p); 172441486Smckusick /* 172541486Smckusick * Dump the remaining UPAGES-1 pages normally 172641486Smckusick */ 172741486Smckusick if (!error) 172849134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 172941486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 173049134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 173141486Smckusick free((caddr_t)faku, M_TEMP); 173241486Smckusick return(error); 173341486Smckusick } 173441486Smckusick 173541486Smckusick /* 173641486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 173741486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 173841486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 173941486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 174057307Shibler * 174157307Shibler * These are still needed as of HP-UX 7.05. 174241486Smckusick */ 174355832Shibler #ifdef COMPAT_OHPUX 174455832Shibler 174545753Smckusick #define HPUX_HZ 50 174645753Smckusick 174757307Shibler #include "sys/times.h" 174841486Smckusick 174941486Smckusick /* from old timeb.h */ 175041486Smckusick struct hpuxtimeb { 175141486Smckusick time_t time; 175241486Smckusick u_short millitm; 175341486Smckusick short timezone; 175441486Smckusick short dstflag; 175541486Smckusick }; 175641486Smckusick 175741486Smckusick /* ye ole stat structure */ 175841486Smckusick struct ohpuxstat { 175953481Smckusick u_short ohst_dev; 176041486Smckusick u_short ohst_ino; 176141486Smckusick u_short ohst_mode; 176241486Smckusick short ohst_nlink; 176341486Smckusick short ohst_uid; 176441486Smckusick short ohst_gid; 176553481Smckusick u_short ohst_rdev; 176641486Smckusick int ohst_size; 176741486Smckusick int ohst_atime; 176841486Smckusick int ohst_mtime; 176941486Smckusick int ohst_ctime; 177041486Smckusick }; 177141486Smckusick 177241486Smckusick /* 177341486Smckusick * SYS V style setpgrp() 177441486Smckusick */ 177543452Shibler ohpuxsetpgrp(p, uap, retval) 177643452Shibler register struct proc *p; 177743452Shibler int *uap, *retval; 177841486Smckusick { 177941486Smckusick if (p->p_pid != p->p_pgid) 178048478Skarels enterpgrp(p, p->p_pid, 0); 178143452Shibler *retval = p->p_pgid; 178245753Smckusick return (0); 178341486Smckusick } 178441486Smckusick 178554917Storek struct ohpuxtime_args { 178654917Storek long *tp; 178754917Storek }; 178843452Shibler ohpuxtime(p, uap, retval) 178943452Shibler struct proc *p; 179054917Storek register struct ohpuxtime_args *uap; 179154917Storek int *retval; 179241486Smckusick { 179345753Smckusick int error = 0; 179441486Smckusick 179541486Smckusick if (uap->tp) 179643452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 179743452Shibler sizeof (long)); 179854917Storek *(time_t *)retval = time.tv_sec; 179944421Skarels return (error); 180041486Smckusick } 180141486Smckusick 180254917Storek struct ohpuxstime_args { 180354917Storek int time; 180454917Storek }; 180543452Shibler ohpuxstime(p, uap, retval) 180643452Shibler struct proc *p; 180754917Storek register struct ohpuxstime_args *uap; 180843452Shibler int *retval; 180941486Smckusick { 181041486Smckusick struct timeval tv; 181143452Shibler int s, error; 181241486Smckusick 181341486Smckusick tv.tv_sec = uap->time; 181441486Smckusick tv.tv_usec = 0; 181548478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 181644421Skarels return (error); 181741486Smckusick 181841486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 181941486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 182041486Smckusick s = splhigh(); time = tv; splx(s); 182141486Smckusick resettodr(); 182244421Skarels return (0); 182341486Smckusick } 182441486Smckusick 182554917Storek struct ohpuxftime_args { 182654917Storek struct hpuxtimeb *tp; 182754917Storek }; 182843452Shibler ohpuxftime(p, uap, retval) 182943452Shibler struct proc *p; 183054917Storek register struct ohpuxftime_args *uap; 183143452Shibler int *retval; 183243452Shibler { 183341486Smckusick struct hpuxtimeb tb; 183441486Smckusick int s; 183541486Smckusick 183641486Smckusick s = splhigh(); 183741486Smckusick tb.time = time.tv_sec; 183841486Smckusick tb.millitm = time.tv_usec / 1000; 183941486Smckusick splx(s); 184041486Smckusick tb.timezone = tz.tz_minuteswest; 184141486Smckusick tb.dstflag = tz.tz_dsttime; 184244421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 184341486Smckusick } 184441486Smckusick 184554917Storek struct ohpuxalarm_args { 184654917Storek int deltat; 184754917Storek }; 184843452Shibler ohpuxalarm(p, uap, retval) 184943452Shibler register struct proc *p; 185054917Storek register struct ohpuxalarm_args *uap; 185143452Shibler int *retval; 185241486Smckusick { 185341486Smckusick int s = splhigh(); 185441486Smckusick 185541486Smckusick untimeout(realitexpire, (caddr_t)p); 185641486Smckusick timerclear(&p->p_realtimer.it_interval); 185743452Shibler *retval = 0; 185841486Smckusick if (timerisset(&p->p_realtimer.it_value) && 185941486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 186043452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 186141486Smckusick if (uap->deltat == 0) { 186241486Smckusick timerclear(&p->p_realtimer.it_value); 186341486Smckusick splx(s); 186444421Skarels return (0); 186541486Smckusick } 186641486Smckusick p->p_realtimer.it_value = time; 186741486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 186841486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 186941486Smckusick splx(s); 187044421Skarels return (0); 187141486Smckusick } 187241486Smckusick 187354917Storek struct ohpuxnice_args { 187454917Storek int niceness; 187554917Storek }; 187643452Shibler ohpuxnice(p, uap, retval) 187743452Shibler register struct proc *p; 187854917Storek register struct ohpuxnice_args *uap; 187943452Shibler int *retval; 188041486Smckusick { 188143452Shibler int error; 188241486Smckusick 188343452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 188443452Shibler if (error == 0) 188543452Shibler *retval = p->p_nice - NZERO; 188644421Skarels return (error); 188741486Smckusick } 188841486Smckusick 188954917Storek struct ohpuxtimes_args { 189054917Storek struct tms *tmsb; 189154917Storek }; 189243452Shibler ohpuxtimes(p, uap, retval) 189343452Shibler struct proc *p; 189454917Storek register struct ohpuxtimes_args *uap; 189554917Storek int *retval; 189641486Smckusick { 189754771Storek struct timeval ru, rs; 189841486Smckusick struct tms atms; 189943452Shibler int error; 190041486Smckusick 190154771Storek calcru(p, &ru, &rs, NULL); 190254771Storek atms.tms_utime = hpuxscale(&ru); 190354771Storek atms.tms_stime = hpuxscale(&rs); 190448478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 190548478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 190643452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 190743452Shibler if (error == 0) 190854917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 190944421Skarels return (error); 191041486Smckusick } 191141486Smckusick 191245753Smckusick /* 191345753Smckusick * Doesn't exactly do what the documentation says. 191445753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 191545753Smckusick * is what HP-UX returns. 191645753Smckusick */ 191745753Smckusick hpuxscale(tvp) 191841486Smckusick register struct timeval *tvp; 191941486Smckusick { 192045753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 192141486Smckusick } 192241486Smckusick 192341486Smckusick /* 192441486Smckusick * Set IUPD and IACC times on file. 192541486Smckusick * Can't set ICHG. 192641486Smckusick */ 192754917Storek struct ohpuxutime_args { 192854917Storek char *fname; 192954917Storek time_t *tptr; 193054917Storek }; 193143452Shibler ohpuxutime(p, uap, retval) 193243452Shibler struct proc *p; 193354917Storek register struct ohpuxutime_args *uap; 193443452Shibler int *retval; 193543452Shibler { 193648478Skarels register struct vnode *vp; 193741486Smckusick struct vattr vattr; 193841486Smckusick time_t tv[2]; 193943452Shibler int error; 194048478Skarels struct nameidata nd; 194141486Smckusick 194241486Smckusick if (uap->tptr) { 194343452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 194443452Shibler if (error) 194544421Skarels return (error); 194641486Smckusick } else 194741486Smckusick tv[0] = tv[1] = time.tv_sec; 194841486Smckusick vattr_null(&vattr); 194954107Smckusick vattr.va_atime.ts_sec = tv[0]; 195054107Smckusick vattr.va_atime.ts_nsec = 0; 195154107Smckusick vattr.va_mtime.ts_sec = tv[1]; 195254107Smckusick vattr.va_mtime.ts_nsec = 0; 195352330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 195452330Smckusick if (error = namei(&nd)) 195544421Skarels return (error); 195652330Smckusick vp = nd.ni_vp; 195742154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 195843452Shibler error = EROFS; 195941486Smckusick else 196052330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 196141486Smckusick vput(vp); 196244421Skarels return (error); 196341486Smckusick } 196441486Smckusick 196543452Shibler ohpuxpause(p, uap, retval) 196643452Shibler struct proc *p; 196743452Shibler int *uap, *retval; 196841486Smckusick { 196949134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 197042155Skarels /* always return EINTR rather than ERESTART... */ 197144421Skarels return (EINTR); 197241486Smckusick } 197341486Smckusick 197441486Smckusick /* 197541486Smckusick * The old fstat system call. 197641486Smckusick */ 197754917Storek struct ohpuxfstat_args { 197854917Storek int fd; 197954917Storek struct ohpuxstat *sb; 198054917Storek }; 198143452Shibler ohpuxfstat(p, uap, retval) 198243452Shibler struct proc *p; 198354917Storek register struct ohpuxfstat_args *uap; 198443452Shibler int *retval; 198543452Shibler { 198645923Smckusick register struct filedesc *fdp = p->p_fd; 198741486Smckusick struct file *fp; 198841486Smckusick 198948478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 199048478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 199144421Skarels return (EBADF); 199243452Shibler if (fp->f_type != DTYPE_VNODE) 199344421Skarels return (EINVAL); 199455282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 199541486Smckusick } 199641486Smckusick 199741486Smckusick /* 199841486Smckusick * Old stat system call. This version follows links. 199941486Smckusick */ 200054917Storek struct ohpuxstat_args { 200154917Storek char *fname; 200254917Storek struct ohpuxstat *sb; 200354917Storek }; 200443452Shibler ohpuxstat(p, uap, retval) 200543452Shibler struct proc *p; 200654917Storek register struct ohpuxstat_args *uap; 200743452Shibler int *retval; 200843452Shibler { 200943452Shibler int error; 201048478Skarels struct nameidata nd; 201141486Smckusick 201252330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 201352330Smckusick if (error = namei(&nd)) 201444421Skarels return (error); 201555282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 201652330Smckusick vput(nd.ni_vp); 201744421Skarels return (error); 201841486Smckusick } 201941486Smckusick 202041486Smckusick int 202155282Smckusick ohpuxstat1(vp, ub, p) 202257307Shibler struct vnode *vp; 202341486Smckusick struct ohpuxstat *ub; 202455282Smckusick struct proc *p; 202541486Smckusick { 202657307Shibler struct ohpuxstat ohsb; 202757307Shibler struct stat sb; 202857307Shibler int error; 202941486Smckusick 203057307Shibler error = vn_stat(vp, &sb, p); 203141486Smckusick if (error) 203257307Shibler return (error); 203357307Shibler 203457307Shibler ohsb.ohst_dev = sb.st_dev; 203557307Shibler ohsb.ohst_ino = sb.st_ino; 203657307Shibler ohsb.ohst_mode = sb.st_mode; 203757307Shibler ohsb.ohst_nlink = sb.st_nlink; 203857307Shibler ohsb.ohst_uid = sb.st_uid; 203957307Shibler ohsb.ohst_gid = sb.st_gid; 204057307Shibler ohsb.ohst_rdev = sb.st_rdev; 204157307Shibler if (sb.st_size < (quad_t)1 << 32) 204257307Shibler ohsb.ohst_size = sb.st_size; 204357307Shibler else 204457307Shibler ohsb.ohst_size = -2; 204557307Shibler ohsb.ohst_atime = sb.st_atime; 204657307Shibler ohsb.ohst_mtime = sb.st_mtime; 204757307Shibler ohsb.ohst_ctime = sb.st_ctime; 204857307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 204941486Smckusick } 205041486Smckusick #endif 205155832Shibler #endif 2052