141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 363734Sbostic * Copyright (c) 1990, 1993 463734Sbostic * 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 * 1264478Shibler * from: Utah $Hdr: hpux_compat.c 1.64 93/08/05$ 1341486Smckusick * 14*64905Shibler * @(#)hpux_compat.c 8.3 (Berkeley) 11/16/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 8064478Shibler #define NERR 83 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, 9264478Shibler /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46, 251,BERR, 9364478Shibler /*80*/ BERR,BERR, 11 9441486Smckusick }; 9541486Smckusick 9643452Shibler notimp(p, uap, retval, code, nargs) 9743452Shibler struct proc *p; 9843452Shibler int *uap, *retval; 9943452Shibler int code, nargs; 10041486Smckusick { 10143452Shibler int error = 0; 10241486Smckusick #ifdef DEBUG 10343452Shibler register int *argp = uap; 10441486Smckusick extern char *hpuxsyscallnames[]; 10541486Smckusick 10654857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10741486Smckusick if (nargs) 10841486Smckusick while (nargs--) 10941486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 11041486Smckusick else 11141486Smckusick printf(")"); 11241486Smckusick printf("\n"); 11341486Smckusick switch (unimpresponse) { 11441486Smckusick case 0: 11543452Shibler error = nosys(p, uap, retval); 11641486Smckusick break; 11741486Smckusick case 1: 11843452Shibler error = EINVAL; 11941486Smckusick break; 12041486Smckusick } 12141486Smckusick #else 12243452Shibler error = nosys(p, uap, retval); 12341486Smckusick #endif 12443452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12544421Skarels return (error); 12641486Smckusick } 12741486Smckusick 12864478Shibler /* 12964478Shibler * HP-UX fork and vfork need to map the EAGAIN return value appropriately. 13064478Shibler */ 13164478Shibler hpuxfork(p, uap, retval) 13264478Shibler struct proc *p; 13364478Shibler struct hpuxwait3_args *uap; 13464478Shibler int *retval; 13564478Shibler { 13664478Shibler int error; 13764478Shibler 13864478Shibler error = fork(p, uap, retval); 13964478Shibler if (error == EAGAIN) 14064478Shibler error = OEAGAIN; 14164478Shibler return (error); 14264478Shibler } 14364478Shibler 14464478Shibler hpuxvfork(p, uap, retval) 14564478Shibler struct proc *p; 14664478Shibler struct hpuxwait3_args *uap; 14764478Shibler int *retval; 14864478Shibler 14964478Shibler { 15064478Shibler int error; 15164478Shibler 15264478Shibler error = vfork(p, uap, retval); 15364478Shibler if (error == EAGAIN) 15464478Shibler error = OEAGAIN; 15564478Shibler return (error); 15664478Shibler } 15764478Shibler 15854917Storek struct hpuxexecv_args { 15954917Storek char *fname; 16054917Storek char **argp; 16154917Storek char **envp; 16254917Storek }; 16348478Skarels hpuxexecv(p, uap, retval) 16448478Skarels struct proc *p; 16554917Storek struct hpuxexecv_args *uap; 16648478Skarels int *retval; 16748478Skarels { 16848478Skarels extern int execve(); 16948478Skarels 17048478Skarels uap->envp = NULL; 17148478Skarels return (execve(p, uap, retval)); 17248478Skarels } 17348478Skarels 17441486Smckusick /* 17554857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 17641486Smckusick * (status pointer, options, rusage) into the kernel rather than 17742352Smckusick * handling it in the C library stub. We also need to map any 17854857Shibler * termination signal from BSD to HP-UX. 17941486Smckusick */ 18054917Storek struct hpuxwait3_args { 18154917Storek int *status; 18254917Storek int options; 18354917Storek int rusage; 18454917Storek }; 18543452Shibler hpuxwait3(p, uap, retval) 18643452Shibler struct proc *p; 18754917Storek struct hpuxwait3_args *uap; 18843452Shibler int *retval; 18943452Shibler { 19041486Smckusick /* rusage pointer must be zero */ 19143452Shibler if (uap->rusage) 19244421Skarels return (EINVAL); 19352381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 19452381Smckusick p->p_md.md_regs[R0] = uap->options; 19552381Smckusick p->p_md.md_regs[R1] = uap->rusage; 19644421Skarels return (hpuxwait(p, uap, retval)); 19741486Smckusick } 19841486Smckusick 19954917Storek struct hpuxwait_args { 20054917Storek int *status; 20154917Storek }; 20243452Shibler hpuxwait(p, uap, retval) 20343452Shibler struct proc *p; 20454917Storek struct hpuxwait_args *uap; 20543452Shibler int *retval; 20641486Smckusick { 20743452Shibler int sig, *statp, error; 20841486Smckusick 20941486Smckusick statp = uap->status; /* owait clobbers first arg */ 21043452Shibler error = owait(p, uap, retval); 21141486Smckusick /* 21241486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21341486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21441486Smckusick */ 21543452Shibler if (error == ERESTART) 21643452Shibler error = EINTR; 21743452Shibler if (error) 21844421Skarels return (error); 21943452Shibler sig = retval[1] & 0xFF; 22041486Smckusick if (sig == WSTOPPED) { 22143452Shibler sig = (retval[1] >> 8) & 0xFF; 22243452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 22341486Smckusick } else if (sig) 22443452Shibler retval[1] = (retval[1] & 0xFF00) | 22541486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 22641486Smckusick if (statp) 22743452Shibler if (suword((caddr_t)statp, retval[1])) 22843452Shibler error = EFAULT; 22944421Skarels return (error); 23041486Smckusick } 23141486Smckusick 23254917Storek struct hpuxwaitpid_args { 23354917Storek int pid; 23454917Storek int *status; 23554917Storek int options; 23654917Storek struct rusage *rusage; /* wait4 arg */ 23754917Storek }; 23843452Shibler hpuxwaitpid(p, uap, retval) 23943452Shibler struct proc *p; 24054917Storek struct hpuxwaitpid_args *uap; 24143452Shibler int *retval; 24243452Shibler { 24355832Shibler int rv, sig, xstat, error; 24442352Smckusick 24542352Smckusick uap->rusage = 0; 24643452Shibler error = wait4(p, uap, retval); 24742352Smckusick /* 24842352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 24942352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 25042352Smckusick */ 25143452Shibler if (error == ERESTART) 25243452Shibler error = EINTR; 25343452Shibler if (error) 25444421Skarels return (error); 25555832Shibler if (uap->status) { 25655832Shibler /* 25755832Shibler * Wait4 already wrote the status out to user space, 25855832Shibler * pull it back, change the signal portion, and write 25955832Shibler * it back out. 26055832Shibler */ 26155832Shibler rv = fuword((caddr_t)uap->status); 26255832Shibler if (WIFSTOPPED(rv)) { 26355832Shibler sig = WSTOPSIG(rv); 26455832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 26555832Shibler } else if (WIFSIGNALED(rv)) { 26655832Shibler sig = WTERMSIG(rv); 26755832Shibler xstat = WEXITSTATUS(rv); 26855832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 26955832Shibler WCOREDUMP(rv); 27055832Shibler } 27155832Shibler (void)suword((caddr_t)uap->status, rv); 27255832Shibler } 27344421Skarels return (error); 27442352Smckusick } 27542352Smckusick 27641486Smckusick /* 27763726Shibler * Old creat system call. 27863726Shibler */ 27963726Shibler struct hpuxcreat_args { 28063726Shibler char *fname; 28163726Shibler int fmode; 28263726Shibler }; 28363726Shibler hpuxcreat(p, uap, retval) 28463726Shibler struct proc *p; 28563726Shibler register struct hpuxcreat_args *uap; 28663726Shibler int *retval; 28763726Shibler { 28863726Shibler struct nargs { 28963726Shibler char *fname; 29063726Shibler int mode; 29163726Shibler int crtmode; 29263726Shibler } openuap; 29363726Shibler 29463726Shibler openuap.fname = uap->fname; 29563726Shibler openuap.crtmode = uap->fmode; 29663726Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 29763726Shibler return (open(p, &openuap, retval)); 29863726Shibler } 29963726Shibler 30063726Shibler /* 30163726Shibler * XXX extensions to the fd_ofileflags flags. 30263726Shibler * Hate to put this there, but they do need to be per-file. 30363726Shibler */ 30463726Shibler #define UF_NONBLOCK_ON 0x10 30563726Shibler #define UF_FNDELAY_ON 0x20 30663726Shibler #define UF_FIONBIO_ON 0x40 30763726Shibler 30863726Shibler /* 30941486Smckusick * Must remap some bits in the mode mask. 31041486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 31163726Shibler * O_NONBLOCK is remapped and remembered, 31263726Shibler * O_FNDELAY is remembered, 31363726Shibler * O_SYNCIO is removed entirely. 31441486Smckusick */ 31554917Storek struct hpuxopen_args { 31654917Storek char *fname; 31754917Storek int mode; 31854917Storek int crtmode; 31954917Storek }; 32043067Skarels hpuxopen(p, uap, retval) 32143067Skarels struct proc *p; 32254917Storek register struct hpuxopen_args *uap; 32343067Skarels int *retval; 32443067Skarels { 32563726Shibler int mode, error; 32641486Smckusick 32741486Smckusick mode = uap->mode; 32863726Shibler uap->mode &= 32963726Shibler ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 33041486Smckusick if (mode & HPUXFCREAT) { 33141486Smckusick /* 33241486Smckusick * simulate the pre-NFS behavior that opening a 33341486Smckusick * file for READ+CREATE ignores the CREATE (unless 33441486Smckusick * EXCL is set in which case we will return the 33541486Smckusick * proper error). 33641486Smckusick */ 33748478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 33849950Smckusick uap->mode |= O_CREAT; 33941486Smckusick } 34041486Smckusick if (mode & HPUXFTRUNC) 34149950Smckusick uap->mode |= O_TRUNC; 34241486Smckusick if (mode & HPUXFEXCL) 34349950Smckusick uap->mode |= O_EXCL; 34463726Shibler if (mode & HPUXNONBLOCK) 34563726Shibler uap->mode |= O_NDELAY; 34663726Shibler error = open(p, uap, retval); 34763726Shibler /* 34863726Shibler * Record non-blocking mode for fcntl, read, write, etc. 34963726Shibler */ 35063726Shibler if (error == 0 && (uap->mode & O_NDELAY)) 35163726Shibler p->p_fd->fd_ofileflags[*retval] |= 35263726Shibler (mode & HPUXNONBLOCK) ? UF_NONBLOCK_ON : UF_FNDELAY_ON; 35363726Shibler return (error); 35441486Smckusick } 35541486Smckusick 35654917Storek struct hpuxfcntl_args { 35754917Storek int fdes; 35854917Storek int cmd; 35954917Storek int arg; 36054917Storek }; 36143452Shibler hpuxfcntl(p, uap, retval) 36243452Shibler struct proc *p; 36354917Storek register struct hpuxfcntl_args *uap; 36443452Shibler int *retval; 36543452Shibler { 36643452Shibler int mode, error; 36749329Shibler char *fp; 36841486Smckusick 36949329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 37049329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 37149329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 37249329Shibler return (EBADF); 37349329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 37449329Shibler } 37541486Smckusick switch (uap->cmd) { 37641486Smckusick case F_SETFL: 37763726Shibler if (uap->arg & HPUXNONBLOCK) 37863726Shibler *fp |= UF_NONBLOCK_ON; 37963726Shibler else 38063726Shibler *fp &= ~UF_NONBLOCK_ON; 38164478Shibler if (uap->arg & HPUXNDELAY) 38249329Shibler *fp |= UF_FNDELAY_ON; 38363726Shibler else 38449329Shibler *fp &= ~UF_FNDELAY_ON; 38563726Shibler if (*fp & (UF_NONBLOCK_ON|UF_FNDELAY_ON|UF_FIONBIO_ON)) 38663726Shibler uap->arg |= FNONBLOCK; 38763726Shibler uap->arg &= ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFREMOTE); 38841486Smckusick break; 38941486Smckusick case F_GETFL: 39041486Smckusick case F_DUPFD: 39141486Smckusick case F_GETFD: 39241486Smckusick case F_SETFD: 39341486Smckusick break; 39441486Smckusick default: 39544421Skarels return (EINVAL); 39641486Smckusick } 39743452Shibler error = fcntl(p, uap, retval); 39849329Shibler if (error == 0 && uap->cmd == F_GETFL) { 39943452Shibler mode = *retval; 40063726Shibler *retval &= ~(O_CREAT|O_TRUNC|O_EXCL); 40163726Shibler if (mode & FNONBLOCK) { 40263726Shibler if (*fp & UF_NONBLOCK_ON) 40363726Shibler *retval |= HPUXNONBLOCK; 40463726Shibler if ((*fp & UF_FNDELAY_ON) == 0) 40564478Shibler *retval &= ~HPUXNDELAY; 40663726Shibler } 40749950Smckusick if (mode & O_CREAT) 40843452Shibler *retval |= HPUXFCREAT; 40949950Smckusick if (mode & O_TRUNC) 41043452Shibler *retval |= HPUXFTRUNC; 41149950Smckusick if (mode & O_EXCL) 41243452Shibler *retval |= HPUXFEXCL; 41341486Smckusick } 41444421Skarels return (error); 41541486Smckusick } 41641486Smckusick 41741486Smckusick /* 41863726Shibler * Read and write calls. Same as BSD except for non-blocking behavior. 41963726Shibler * There are three types of non-blocking reads/writes in HP-UX checked 42063726Shibler * in the following order: 42149329Shibler * 42263726Shibler * O_NONBLOCK: return -1 and errno == EAGAIN 42363726Shibler * O_NDELAY: return 0 42463726Shibler * FIOSNBIO: return -1 and errno == EWOULDBLOCK 42541486Smckusick */ 42663726Shibler struct hpuxrw_args { 42763726Shibler int fd; 42854917Storek }; 42963726Shibler 43043452Shibler hpuxread(p, uap, retval) 43143452Shibler struct proc *p; 43263726Shibler struct hpuxrw_args *uap; 43343452Shibler int *retval; 43441486Smckusick { 43543452Shibler int error; 43641486Smckusick 43743452Shibler error = read(p, uap, retval); 43863726Shibler if (error == EWOULDBLOCK) { 43963726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 44063726Shibler 44163726Shibler if (*fp & UF_NONBLOCK_ON) { 44263726Shibler *retval = -1; 44364478Shibler error = OEAGAIN; 44463726Shibler } else if (*fp & UF_FNDELAY_ON) { 44563726Shibler *retval = 0; 44663726Shibler error = 0; 44763726Shibler } 44841486Smckusick } 44944421Skarels return (error); 45041486Smckusick } 45141486Smckusick 45243452Shibler hpuxwrite(p, uap, retval) 45343452Shibler struct proc *p; 45463726Shibler struct hpuxrw_args *uap; 45543452Shibler int *retval; 45641486Smckusick { 45743452Shibler int error; 45841486Smckusick 45943452Shibler error = write(p, uap, retval); 46063726Shibler if (error == EWOULDBLOCK) { 46163726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 46263726Shibler 46363726Shibler if (*fp & UF_NONBLOCK_ON) { 46463726Shibler *retval = -1; 46564478Shibler error = OEAGAIN; 46663726Shibler } else if (*fp & UF_FNDELAY_ON) { 46763726Shibler *retval = 0; 46863726Shibler error = 0; 46963726Shibler } 47041486Smckusick } 47144421Skarels return (error); 47241486Smckusick } 47341486Smckusick 47443452Shibler hpuxreadv(p, uap, retval) 47543452Shibler struct proc *p; 47663726Shibler struct hpuxrw_args *uap; 47743452Shibler int *retval; 47841486Smckusick { 47943452Shibler int error; 48041486Smckusick 48143452Shibler error = readv(p, uap, retval); 48263726Shibler if (error == EWOULDBLOCK) { 48363726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 48463726Shibler 48563726Shibler if (*fp & UF_NONBLOCK_ON) { 48663726Shibler *retval = -1; 48764478Shibler error = OEAGAIN; 48863726Shibler } else if (*fp & UF_FNDELAY_ON) { 48963726Shibler *retval = 0; 49063726Shibler error = 0; 49163726Shibler } 49241486Smckusick } 49344421Skarels return (error); 49441486Smckusick } 49541486Smckusick 49643452Shibler hpuxwritev(p, uap, retval) 49743452Shibler struct proc *p; 49863726Shibler struct hpuxrw_args *uap; 49943452Shibler int *retval; 50041486Smckusick { 50143452Shibler int error; 50241486Smckusick 50343452Shibler error = writev(p, uap, retval); 50463726Shibler if (error == EWOULDBLOCK) { 50563726Shibler char *fp = &p->p_fd->fd_ofileflags[uap->fd]; 50663726Shibler 50763726Shibler if (*fp & UF_NONBLOCK_ON) { 50863726Shibler *retval = -1; 50964478Shibler error = OEAGAIN; 51063726Shibler } else if (*fp & UF_FNDELAY_ON) { 51163726Shibler *retval = 0; 51263726Shibler error = 0; 51363726Shibler } 51441486Smckusick } 51544421Skarels return (error); 51641486Smckusick } 51741486Smckusick 51841486Smckusick /* 51941486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 52054857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 52141486Smckusick */ 52254917Storek struct hpuxdup_args { 52354917Storek int i; 52454917Storek }; 52543452Shibler hpuxdup(p, uap, retval) 52643452Shibler struct proc *p; 52754917Storek register struct hpuxdup_args *uap; 52843452Shibler int *retval; 52941486Smckusick { 53045923Smckusick register struct filedesc *fdp = p->p_fd; 53141486Smckusick struct file *fp; 53243452Shibler int fd, error; 53341486Smckusick 53448478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 53548478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 53644421Skarels return (EBADF); 53748478Skarels if (error = fdalloc(p, 0, &fd)) 53844421Skarels return (error); 53948478Skarels fdp->fd_ofiles[fd] = fp; 54048478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 54145923Smckusick fp->f_count++; 54245923Smckusick if (fd > fdp->fd_lastfile) 54345923Smckusick fdp->fd_lastfile = fd; 54443452Shibler *retval = fd; 54544421Skarels return (0); 54641486Smckusick } 54741486Smckusick 54854917Storek struct hpuxutssys_args { 54954917Storek struct hpuxutsname *uts; 55054917Storek int dev; 55154917Storek int request; 55254917Storek }; 55345753Smckusick hpuxutssys(p, uap, retval) 55443452Shibler struct proc *p; 55554917Storek register struct hpuxutssys_args *uap; 55643452Shibler int *retval; 55743452Shibler { 55841486Smckusick register int i; 55943452Shibler int error; 56041486Smckusick 56141486Smckusick switch (uap->request) { 56241486Smckusick /* uname */ 56341486Smckusick case 0: 56441486Smckusick /* fill in machine type */ 56541486Smckusick switch (machineid) { 56641486Smckusick case HP_320: 56741486Smckusick protoutsname.machine[6] = '2'; 56841486Smckusick break; 56941486Smckusick /* includes 318 and 319 */ 57041486Smckusick case HP_330: 57141486Smckusick protoutsname.machine[6] = '3'; 57241486Smckusick break; 57341486Smckusick case HP_340: 57441486Smckusick protoutsname.machine[6] = '4'; 57541486Smckusick break; 57641486Smckusick case HP_350: 57741486Smckusick protoutsname.machine[6] = '5'; 57841486Smckusick break; 57941486Smckusick case HP_360: 58041486Smckusick protoutsname.machine[6] = '6'; 58141486Smckusick break; 58241486Smckusick case HP_370: 58341486Smckusick protoutsname.machine[6] = '7'; 58441486Smckusick break; 58543452Shibler /* includes 345 */ 58643452Shibler case HP_375: 58743452Shibler protoutsname.machine[6] = '7'; 58843452Shibler protoutsname.machine[7] = '5'; 58943452Shibler break; 59054857Shibler /* includes 425 */ 59154857Shibler case HP_380: 59254857Shibler protoutsname.machine[6] = '8'; 59354857Shibler break; 59457307Shibler case HP_433: 59557307Shibler protoutsname.machine[5] = '4'; 59657307Shibler protoutsname.machine[6] = '3'; 59757307Shibler protoutsname.machine[7] = '3'; 59857307Shibler break; 59941486Smckusick } 60041486Smckusick /* copy hostname (sans domain) to nodename */ 60149329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 60241486Smckusick protoutsname.nodename[i] = hostname[i]; 60349329Shibler protoutsname.nodename[i] = '\0'; 60443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 60543452Shibler sizeof(struct hpuxutsname)); 60641486Smckusick break; 60745753Smckusick 60845753Smckusick /* gethostname */ 60945753Smckusick case 5: 61045753Smckusick /* uap->dev is length */ 61145753Smckusick if (uap->dev > hostnamelen + 1) 61245753Smckusick uap->dev = hostnamelen + 1; 61345753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 61445753Smckusick uap->dev); 61545753Smckusick break; 61645753Smckusick 61745753Smckusick case 1: /* ?? */ 61845753Smckusick case 2: /* ustat */ 61945753Smckusick case 3: /* ?? */ 62045753Smckusick case 4: /* sethostname */ 62141486Smckusick default: 62243452Shibler error = EINVAL; 62341486Smckusick break; 62441486Smckusick } 62544421Skarels return (error); 62641486Smckusick } 62741486Smckusick 62854917Storek struct hpuxsysconf_args { 62954917Storek int name; 63054917Storek }; 63153922Shibler hpuxsysconf(p, uap, retval) 63253922Shibler struct proc *p; 63354917Storek struct hpuxsysconf_args *uap; 63453922Shibler int *retval; 63553922Shibler { 63653922Shibler switch (uap->name) { 63753922Shibler 638*64905Shibler /* clock ticks per second */ 639*64905Shibler case HPUX_SYSCONF_CLKTICK: 640*64905Shibler *retval = hz; 641*64905Shibler break; 642*64905Shibler 64353922Shibler /* open files */ 64453922Shibler case HPUX_SYSCONF_OPENMAX: 64553922Shibler *retval = NOFILE; 64653922Shibler break; 64753922Shibler 64853922Shibler /* architecture */ 64953922Shibler case HPUX_SYSCONF_CPUTYPE: 65053922Shibler switch (machineid) { 65153922Shibler case HP_320: 65253922Shibler case HP_330: 65353922Shibler case HP_350: 65453922Shibler *retval = HPUX_SYSCONF_CPUM020; 65553922Shibler break; 65653922Shibler case HP_340: 65753922Shibler case HP_360: 65853922Shibler case HP_370: 65953922Shibler case HP_375: 66053922Shibler *retval = HPUX_SYSCONF_CPUM030; 66153922Shibler break; 66253922Shibler case HP_380: 66357307Shibler case HP_433: 66453922Shibler *retval = HPUX_SYSCONF_CPUM040; 66553922Shibler break; 66653922Shibler } 66753922Shibler break; 66853922Shibler default: 66954857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 67053922Shibler return (EINVAL); 67153922Shibler } 67253922Shibler return (0); 67353922Shibler } 67453922Shibler 67554917Storek struct hpuxstat_args { 67654917Storek char *fname; 67754917Storek struct hpuxstat *hsb; 67854917Storek }; 67943452Shibler hpuxstat(p, uap, retval) 68043452Shibler struct proc *p; 68154917Storek struct hpuxstat_args *uap; 68243452Shibler int *retval; 68343452Shibler { 68455282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 68541486Smckusick } 68641486Smckusick 68754917Storek struct hpuxlstat_args { 68854917Storek char *fname; 68954917Storek struct hpuxstat *hsb; 69054917Storek }; 69143452Shibler hpuxlstat(p, uap, retval) 69243452Shibler struct proc *p; 69354917Storek struct hpuxlstat_args *uap; 69443452Shibler int *retval; 69541486Smckusick { 69655282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 69741486Smckusick } 69841486Smckusick 69954917Storek struct hpuxfstat_args { 70054917Storek int fdes; 70154917Storek struct hpuxstat *hsb; 70254917Storek }; 70343452Shibler hpuxfstat(p, uap, retval) 70443452Shibler struct proc *p; 70554917Storek register struct hpuxfstat_args *uap; 70643452Shibler int *retval; 70741486Smckusick { 70845923Smckusick register struct filedesc *fdp = p->p_fd; 70941486Smckusick register struct file *fp; 71041486Smckusick struct stat sb; 71143452Shibler int error; 71241486Smckusick 71348478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 71448478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 71544421Skarels return (EBADF); 71643452Shibler 71741486Smckusick switch (fp->f_type) { 71841486Smckusick 71941486Smckusick case DTYPE_VNODE: 72055282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 72141486Smckusick break; 72241486Smckusick 72341486Smckusick case DTYPE_SOCKET: 72455282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 72541486Smckusick break; 72641486Smckusick 72741486Smckusick default: 72841486Smckusick panic("fstat"); 72941486Smckusick /*NOTREACHED*/ 73041486Smckusick } 73141486Smckusick /* is this right for sockets?? */ 73243452Shibler if (error == 0) 73343452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 73444421Skarels return (error); 73541486Smckusick } 73641486Smckusick 73754917Storek struct hpuxulimit_args { 73854917Storek int cmd; 73954917Storek long newlimit; 74054917Storek }; 74143452Shibler hpuxulimit(p, uap, retval) 74243452Shibler struct proc *p; 74354917Storek register struct hpuxulimit_args *uap; 74453481Smckusick long *retval; 74543452Shibler { 74641486Smckusick struct rlimit *limp; 74743452Shibler int error = 0; 74841486Smckusick 74948478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 75041486Smckusick switch (uap->cmd) { 75141486Smckusick case 2: 75241486Smckusick uap->newlimit *= 512; 75341486Smckusick if (uap->newlimit > limp->rlim_max && 75448478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 75541486Smckusick break; 75641486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 75741486Smckusick /* else fall into... */ 75841486Smckusick 75941486Smckusick case 1: 76045753Smckusick *retval = limp->rlim_max / 512; 76141486Smckusick break; 76241486Smckusick 76341486Smckusick case 3: 76448478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 76548478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 76641486Smckusick break; 76741486Smckusick 76841486Smckusick default: 76943452Shibler error = EINVAL; 77041486Smckusick break; 77141486Smckusick } 77244421Skarels return (error); 77341486Smckusick } 77441486Smckusick 77541486Smckusick /* 77641486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 77741486Smckusick * values -16 (high) thru -1 (low). 77841486Smckusick */ 77954917Storek struct hpuxrtprio_args { 78054917Storek int pid; 78154917Storek int prio; 78254917Storek }; 78343452Shibler hpuxrtprio(cp, uap, retval) 78443452Shibler struct proc *cp; 78554917Storek register struct hpuxrtprio_args *uap; 78643452Shibler int *retval; 78743452Shibler { 78841486Smckusick struct proc *p; 78943452Shibler int nice, error; 79041486Smckusick 79141486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 79243452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 79344421Skarels return (EINVAL); 79441486Smckusick if (uap->pid == 0) 79543452Shibler p = cp; 79643452Shibler else if ((p = pfind(uap->pid)) == 0) 79744421Skarels return (ESRCH); 79841486Smckusick nice = p->p_nice; 79941486Smckusick if (nice < NZERO) 80043452Shibler *retval = (nice + 16) << 3; 80141486Smckusick else 80243452Shibler *retval = RTPRIO_RTOFF; 80341486Smckusick switch (uap->prio) { 80441486Smckusick 80541486Smckusick case RTPRIO_NOCHG: 80644421Skarels return (0); 80741486Smckusick 80841486Smckusick case RTPRIO_RTOFF: 80941486Smckusick if (nice >= NZERO) 81044421Skarels return (0); 81141486Smckusick nice = NZERO; 81241486Smckusick break; 81341486Smckusick 81441486Smckusick default: 81541486Smckusick nice = (uap->prio >> 3) - 16; 81641486Smckusick break; 81741486Smckusick } 81843452Shibler error = donice(cp, p, nice); 81943452Shibler if (error == EACCES) 82043452Shibler error = EPERM; 82144421Skarels return (error); 82241486Smckusick } 82341486Smckusick 82454917Storek struct hpuxadvise_args { 82554917Storek int arg; 82654917Storek }; 82743452Shibler hpuxadvise(p, uap, retval) 82843452Shibler struct proc *p; 82954917Storek struct hpuxadvise_args *uap; 83043452Shibler int *retval; 83141486Smckusick { 83243452Shibler int error = 0; 83341486Smckusick 83441486Smckusick switch (uap->arg) { 83541486Smckusick case 0: 83657307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 83741486Smckusick break; 83841486Smckusick case 1: 83941486Smckusick ICIA(); 84041486Smckusick break; 84141486Smckusick case 2: 84241486Smckusick DCIA(); 84341486Smckusick break; 84441486Smckusick default: 84543452Shibler error = EINVAL; 84641486Smckusick break; 84741486Smckusick } 84844421Skarels return (error); 84941486Smckusick } 85041486Smckusick 85154917Storek struct hpuxptrace_args { 85254917Storek int req; 85354917Storek int pid; 85454917Storek int *addr; 85554917Storek int data; 85654917Storek }; 85743452Shibler hpuxptrace(p, uap, retval) 85843452Shibler struct proc *p; 85954917Storek struct hpuxptrace_args *uap; 86043452Shibler int *retval; 86143452Shibler { 86257307Shibler int error, isps = 0; 86357307Shibler struct proc *cp; 86441486Smckusick 86557307Shibler switch (uap->req) { 86657307Shibler /* map signal */ 86757307Shibler case PT_STEP: 86857307Shibler case PT_CONTINUE: 86941486Smckusick if (uap->data) { 87041486Smckusick uap->data = hpuxtobsdsig(uap->data); 87141486Smckusick if (uap->data == 0) 87241486Smckusick uap->data = NSIG; 87341486Smckusick } 87457307Shibler break; 87557307Shibler /* map u-area offset */ 87657307Shibler case PT_READ_U: 87757307Shibler case PT_WRITE_U: 87857307Shibler /* 87957307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 88057307Shibler * to be called in the child context (procxmt) but we 88157307Shibler * do it here in the parent context to avoid hacks in 88257307Shibler * the MI sys_process.c file. This works only because 88357307Shibler * we can access the child's md_regs pointer and it 88457307Shibler * has the correct value (the child has already trapped 88557307Shibler * into the kernel). 88657307Shibler */ 88757307Shibler if ((cp = pfind(uap->pid)) == 0) 88857307Shibler return (ESRCH); 88957307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 89057307Shibler 89157307Shibler /* 89257307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 89357307Shibler * to write PS actually contain the PS in the high word 89457307Shibler * and the high half of the PC (the following register) 89557307Shibler * in the low word. Move the PS value to where BSD 89657307Shibler * expects it. 89757307Shibler */ 89857307Shibler if (isps && uap->req == PT_WRITE_U) 89957307Shibler uap->data >>= 16; 90057307Shibler break; 90141486Smckusick } 90243452Shibler error = ptrace(p, uap, retval); 90357307Shibler /* 90457307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 90557307Shibler * Note that we do not return the high part of PC like HP-UX 90657307Shibler * would, but the HP-UX debuggers don't require it. 90757307Shibler */ 90857307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 90957307Shibler *retval <<= 16; 91044421Skarels return (error); 91141486Smckusick } 91241486Smckusick 91354917Storek struct hpuxgetdomainname_args { 91454917Storek char *domainname; 91554917Storek u_int len; 91654917Storek }; 91743452Shibler hpuxgetdomainname(p, uap, retval) 91843452Shibler struct proc *p; 91954917Storek register struct hpuxgetdomainname_args *uap; 92043452Shibler int *retval; 92143452Shibler { 92241486Smckusick if (uap->len > domainnamelen + 1) 92341486Smckusick uap->len = domainnamelen + 1; 92444421Skarels return (copyout(domainname, uap->domainname, uap->len)); 92541486Smckusick } 92641486Smckusick 92754917Storek struct hpuxsetdomainname_args { 92854917Storek char *domainname; 92954917Storek u_int len; 93054917Storek }; 93143452Shibler hpuxsetdomainname(p, uap, retval) 93243452Shibler struct proc *p; 93354917Storek register struct hpuxsetdomainname_args *uap; 93443452Shibler int *retval; 93543452Shibler { 93643452Shibler int error; 93741486Smckusick 93848478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 93944421Skarels return (error); 94043452Shibler if (uap->len > sizeof (domainname) - 1) 94144421Skarels return (EINVAL); 94241486Smckusick domainnamelen = uap->len; 94343452Shibler error = copyin(uap->domainname, domainname, uap->len); 94441486Smckusick domainname[domainnamelen] = 0; 94544421Skarels return (error); 94641486Smckusick } 94741486Smckusick 94841486Smckusick #ifdef SYSVSHM 94956506Sbostic #include <sys/shm.h> 95054857Shibler 95143452Shibler hpuxshmat(p, uap, retval) 95243452Shibler struct proc *p; 95343452Shibler int *uap, *retval; 95441486Smckusick { 95544421Skarels return (shmat(p, uap, retval)); 95641486Smckusick } 95741486Smckusick 95843452Shibler hpuxshmdt(p, uap, retval) 95943452Shibler struct proc *p; 96043452Shibler int *uap, *retval; 96141486Smckusick { 96244421Skarels return (shmdt(p, uap, retval)); 96341486Smckusick } 96441486Smckusick 96543452Shibler hpuxshmget(p, uap, retval) 96643452Shibler struct proc *p; 96743452Shibler int *uap, *retval; 96841486Smckusick { 96944421Skarels return (shmget(p, uap, retval)); 97041486Smckusick } 97154857Shibler 97264478Shibler hpuxshmctl(p, uap, retval) 97364478Shibler struct proc *p; 97464478Shibler int *uap, *retval; 97564478Shibler { 97664478Shibler return (hpuxshmctl1(p, uap, retval, 0)); 97764478Shibler } 97864478Shibler 97964478Shibler hpuxnshmctl(p, uap, retval) 98064478Shibler struct proc *p; 98164478Shibler int *uap, *retval; 98264478Shibler { 98364478Shibler return (hpuxshmctl1(p, uap, retval, 1)); 98464478Shibler } 98564478Shibler 98654857Shibler /* 98754857Shibler * Handle HP-UX specific commands. 98854857Shibler */ 98954917Storek struct hpuxshmctl_args { 99054917Storek int shmid; 99154917Storek int cmd; 99254917Storek caddr_t buf; 99354917Storek }; 99464478Shibler hpuxshmctl1(p, uap, retval, isnew) 99554857Shibler struct proc *p; 99654917Storek struct hpuxshmctl_args *uap; 99754857Shibler int *retval; 99864478Shibler int isnew; 99954857Shibler { 100054857Shibler register struct shmid_ds *shp; 100154857Shibler register struct ucred *cred = p->p_ucred; 100264478Shibler struct hpuxshmid_ds sbuf; 100354857Shibler int error; 100454857Shibler 100554857Shibler if (error = shmvalid(uap->shmid)) 100654857Shibler return (error); 100754857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 100864478Shibler switch (uap->cmd) { 100964478Shibler case SHM_LOCK: 101064478Shibler case SHM_UNLOCK: 101154857Shibler /* don't really do anything, but make them think we did */ 101254857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 101354857Shibler cred->cr_uid != shp->shm_perm.cuid) 101454857Shibler return (EPERM); 101554857Shibler return (0); 101664478Shibler 101764478Shibler case IPC_STAT: 101864478Shibler if (!isnew) 101964478Shibler break; 102064478Shibler error = ipcaccess(&shp->shm_perm, IPC_R, cred); 102164478Shibler if (error == 0) { 102264478Shibler sbuf.shm_perm.uid = shp->shm_perm.uid; 102364478Shibler sbuf.shm_perm.gid = shp->shm_perm.gid; 102464478Shibler sbuf.shm_perm.cuid = shp->shm_perm.cuid; 102564478Shibler sbuf.shm_perm.cgid = shp->shm_perm.cgid; 102664478Shibler sbuf.shm_perm.mode = shp->shm_perm.mode; 102764478Shibler sbuf.shm_perm.seq = shp->shm_perm.seq; 102864478Shibler sbuf.shm_perm.key = shp->shm_perm.key; 102964478Shibler sbuf.shm_segsz = shp->shm_segsz; 103064478Shibler sbuf.shm_ptbl = shp->shm_handle; /* XXX */ 103164478Shibler sbuf.shm_lpid = shp->shm_lpid; 103264478Shibler sbuf.shm_cpid = shp->shm_cpid; 103364478Shibler sbuf.shm_nattch = shp->shm_nattch; 103464478Shibler sbuf.shm_cnattch = shp->shm_nattch; /* XXX */ 103564478Shibler sbuf.shm_atime = shp->shm_atime; 103664478Shibler sbuf.shm_dtime = shp->shm_dtime; 103764478Shibler sbuf.shm_ctime = shp->shm_ctime; 103864478Shibler error = copyout((caddr_t)&sbuf, uap->buf, sizeof sbuf); 103964478Shibler } 104064478Shibler return (error); 104164478Shibler 104264478Shibler case IPC_SET: 104364478Shibler if (!isnew) 104464478Shibler break; 104564478Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 104664478Shibler cred->cr_uid != shp->shm_perm.cuid) { 104764478Shibler return (EPERM); 104864478Shibler } 104964478Shibler error = copyin(uap->buf, (caddr_t)&sbuf, sizeof sbuf); 105064478Shibler if (error == 0) { 105164478Shibler shp->shm_perm.uid = sbuf.shm_perm.uid; 105264478Shibler shp->shm_perm.gid = sbuf.shm_perm.gid; 105364478Shibler shp->shm_perm.mode = (shp->shm_perm.mode & ~0777) 105464478Shibler | (sbuf.shm_perm.mode & 0777); 105564478Shibler shp->shm_ctime = time.tv_sec; 105664478Shibler } 105764478Shibler return (error); 105854857Shibler } 105954857Shibler return (shmctl(p, uap, retval)); 106054857Shibler } 106141486Smckusick #endif 106241486Smckusick 106341486Smckusick /* 106441486Smckusick * Fake semaphore routines, just don't return an error. 106541486Smckusick * Should be adequate for starbase to run. 106641486Smckusick */ 106754917Storek struct hpuxsemctl_args { 106854917Storek int semid; 106954917Storek u_int semnum; 107054917Storek int cmd; 107154917Storek int arg; 107254917Storek }; 107343452Shibler hpuxsemctl(p, uap, retval) 107443452Shibler struct proc *p; 107554917Storek struct hpuxsemctl_args *uap; 107643452Shibler int *retval; 107743452Shibler { 107841486Smckusick /* XXX: should do something here */ 107944421Skarels return (0); 108041486Smckusick } 108141486Smckusick 108254917Storek struct hpuxsemget_args { 108354917Storek key_t key; 108454917Storek int nsems; 108554917Storek int semflg; 108654917Storek }; 108743452Shibler hpuxsemget(p, uap, retval) 108843452Shibler struct proc *p; 108954917Storek struct hpuxsemget_args *uap; 109043452Shibler int *retval; 109143452Shibler { 109241486Smckusick /* XXX: should do something here */ 109344421Skarels return (0); 109441486Smckusick } 109541486Smckusick 109654917Storek struct hpuxsemop_args { 109754917Storek int semid; 109854917Storek struct sembuf *sops; 109954917Storek u_int nsops; 110054917Storek }; 110143452Shibler hpuxsemop(p, uap, retval) 110243452Shibler struct proc *p; 110354917Storek struct hpuxsemop_args *uap; 110443452Shibler int *retval; 110543452Shibler { 110641486Smckusick /* XXX: should do something here */ 110744421Skarels return (0); 110841486Smckusick } 110941486Smckusick 111057307Shibler /* 111157307Shibler * HP-UX mmap() emulation (mainly for shared library support). 111257307Shibler */ 111357307Shibler struct hpuxmmap_args { 111457307Shibler caddr_t addr; 111557307Shibler int len; 111657307Shibler int prot; 111757307Shibler int flags; 111857307Shibler int fd; 111957307Shibler long pos; 112057307Shibler }; 112157307Shibler hpuxmmap(p, uap, retval) 112257307Shibler struct proc *p; 112357307Shibler struct hpuxmmap_args *uap; 112457307Shibler int *retval; 112557307Shibler { 112657307Shibler struct mmap_args { 112757307Shibler caddr_t addr; 112857307Shibler int len; 112957307Shibler int prot; 113057307Shibler int flags; 113157307Shibler int fd; 113257307Shibler long pad; 113357307Shibler off_t pos; 113457307Shibler } nargs; 113557307Shibler 113657307Shibler nargs.addr = uap->addr; 113757307Shibler nargs.len = uap->len; 113857307Shibler nargs.prot = uap->prot; 113957307Shibler nargs.flags = uap->flags & 114057307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 114157307Shibler if (uap->flags & HPUXMAP_FIXED) 114257307Shibler nargs.flags |= MAP_FIXED; 114357307Shibler if (uap->flags & HPUXMAP_ANON) 114457307Shibler nargs.flags |= MAP_ANON; 114557307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 114657307Shibler nargs.pos = uap->pos; 114763440Sbostic return (mmap(p, &nargs, retval)); 114857307Shibler } 114957307Shibler 115054857Shibler /* convert from BSD to HP-UX errno */ 115141486Smckusick bsdtohpuxerrno(err) 115241486Smckusick int err; 115341486Smckusick { 115441486Smckusick if (err < 0 || err >= NERR) 115541486Smckusick return(BERR); 115641486Smckusick return((int)bsdtohpuxerrnomap[err]); 115741486Smckusick } 115841486Smckusick 115955282Smckusick hpuxstat1(fname, hsb, follow, p) 116041486Smckusick char *fname; 116141486Smckusick struct hpuxstat *hsb; 116241486Smckusick int follow; 116355282Smckusick struct proc *p; 116441486Smckusick { 116548478Skarels int error; 116641486Smckusick struct stat sb; 116748478Skarels struct nameidata nd; 116841486Smckusick 116955282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 117052330Smckusick if (error = namei(&nd)) 117141486Smckusick return (error); 117255282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 117352330Smckusick vput(nd.ni_vp); 117441486Smckusick if (error == 0) 117541486Smckusick error = bsdtohpuxstat(&sb, hsb); 117641486Smckusick return (error); 117741486Smckusick } 117841486Smckusick 117941486Smckusick #include "grf.h" 118053922Shibler #if NGRF > 0 118153922Shibler #ifdef __STDC__ 118253922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 118353922Shibler #else 118453922Shibler extern int grfopen(); 118553922Shibler #endif 118653922Shibler #endif 118741486Smckusick 118853922Shibler #define NHIL 1 /* XXX */ 118953922Shibler #if NHIL > 0 119053922Shibler #ifdef __STDC__ 119153922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 119253922Shibler #else 119353922Shibler extern int hilopen(); 119453922Shibler #endif 119553922Shibler #endif 119653922Shibler 119756506Sbostic #include <sys/conf.h> 119853922Shibler 119941486Smckusick bsdtohpuxstat(sb, hsb) 120041486Smckusick struct stat *sb; 120141486Smckusick struct hpuxstat *hsb; 120241486Smckusick { 120341486Smckusick struct hpuxstat ds; 120441486Smckusick 120541486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 120653481Smckusick ds.hst_dev = (u_short)sb->st_dev; 120741486Smckusick ds.hst_ino = (u_long)sb->st_ino; 120841486Smckusick ds.hst_mode = sb->st_mode; 120941486Smckusick ds.hst_nlink = sb->st_nlink; 121041486Smckusick ds.hst_uid = (u_short)sb->st_uid; 121141486Smckusick ds.hst_gid = (u_short)sb->st_gid; 121257307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 121357307Shibler 121453922Shibler /* XXX: I don't want to talk about it... */ 121553922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 121641486Smckusick #if NGRF > 0 121753922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 121853922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 121941486Smckusick #endif 122053922Shibler #if NHIL > 0 122153922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 122253922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 122353922Shibler #endif 122453922Shibler ; 122557307Shibler } 122653481Smckusick if (sb->st_size < (quad_t)1 << 32) 122753481Smckusick ds.hst_size = (long)sb->st_size; 122853481Smckusick else 122953481Smckusick ds.hst_size = -2; 123041486Smckusick ds.hst_atime = sb->st_atime; 123141486Smckusick ds.hst_mtime = sb->st_mtime; 123241486Smckusick ds.hst_ctime = sb->st_ctime; 123341486Smckusick ds.hst_blksize = sb->st_blksize; 123441486Smckusick ds.hst_blocks = sb->st_blocks; 123541486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 123641486Smckusick } 123741486Smckusick 123841486Smckusick hpuxtobsdioctl(com) 123941486Smckusick int com; 124041486Smckusick { 124141486Smckusick switch (com) { 124241486Smckusick case HPUXTIOCSLTC: 124341486Smckusick com = TIOCSLTC; break; 124441486Smckusick case HPUXTIOCGLTC: 124541486Smckusick com = TIOCGLTC; break; 124641486Smckusick case HPUXTIOCSPGRP: 124741486Smckusick com = TIOCSPGRP; break; 124841486Smckusick case HPUXTIOCGPGRP: 124941486Smckusick com = TIOCGPGRP; break; 125041486Smckusick case HPUXTIOCLBIS: 125141486Smckusick com = TIOCLBIS; break; 125241486Smckusick case HPUXTIOCLBIC: 125341486Smckusick com = TIOCLBIC; break; 125441486Smckusick case HPUXTIOCLSET: 125541486Smckusick com = TIOCLSET; break; 125641486Smckusick case HPUXTIOCLGET: 125741486Smckusick com = TIOCLGET; break; 125864478Shibler case HPUXTIOCGWINSZ: 125964478Shibler com = TIOCGWINSZ; break; 126064478Shibler case HPUXTIOCSWINSZ: 126164478Shibler com = TIOCSWINSZ; break; 126241486Smckusick } 126341486Smckusick return(com); 126441486Smckusick } 126541486Smckusick 126641486Smckusick /* 126754857Shibler * HP-UX ioctl system call. The differences here are: 126841486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 126949329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 127041486Smckusick * the sgttyb struct is 2 bytes longer 127141486Smckusick */ 127254917Storek struct hpuxioctl_args { 127354917Storek int fdes; 127454917Storek int cmd; 127554917Storek caddr_t cmarg; 127654917Storek }; 127743452Shibler hpuxioctl(p, uap, retval) 127843452Shibler struct proc *p; 127954917Storek register struct hpuxioctl_args *uap; 128043452Shibler int *retval; 128143452Shibler { 128245923Smckusick register struct filedesc *fdp = p->p_fd; 128343452Shibler register struct file *fp; 128443452Shibler register int com, error; 128541486Smckusick register u_int size; 128641486Smckusick caddr_t memp = 0; 128741486Smckusick #define STK_PARAMS 128 128841486Smckusick char stkbuf[STK_PARAMS]; 128941486Smckusick caddr_t data = stkbuf; 129041486Smckusick 129141486Smckusick com = uap->cmd; 129241486Smckusick 129341486Smckusick /* XXX */ 129443452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 129545923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 129641486Smckusick 129748478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 129848478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 129944421Skarels return (EBADF); 130043452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 130144421Skarels return (EBADF); 130241486Smckusick 130341486Smckusick /* 130441486Smckusick * Interpret high order word to find 130541486Smckusick * amount of data to be copied to/from the 130641486Smckusick * user's address space. 130741486Smckusick */ 130841486Smckusick size = IOCPARM_LEN(com); 130943452Shibler if (size > IOCPARM_MAX) 131044421Skarels return (ENOTTY); 131141486Smckusick if (size > sizeof (stkbuf)) { 131243452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 131341486Smckusick data = memp; 131441486Smckusick } 131541486Smckusick if (com&IOC_IN) { 131641486Smckusick if (size) { 131743452Shibler error = copyin(uap->cmarg, data, (u_int)size); 131843452Shibler if (error) { 131941486Smckusick if (memp) 132041486Smckusick free(memp, M_IOCTLOPS); 132144421Skarels return (error); 132241486Smckusick } 132341486Smckusick } else 132441486Smckusick *(caddr_t *)data = uap->cmarg; 132541486Smckusick } else if ((com&IOC_OUT) && size) 132641486Smckusick /* 132743452Shibler * Zero the buffer so the user always 132843452Shibler * gets back something deterministic. 132941486Smckusick */ 133041486Smckusick bzero(data, size); 133141486Smckusick else if (com&IOC_VOID) 133241486Smckusick *(caddr_t *)data = uap->cmarg; 133341486Smckusick 133441486Smckusick switch (com) { 133541486Smckusick 133649329Shibler case HPUXFIOSNBIO: 133749329Shibler { 133849329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 133949329Shibler int tmp; 134049329Shibler 134149329Shibler if (*(int *)data) 134249329Shibler *ofp |= UF_FIONBIO_ON; 134349329Shibler else 134449329Shibler *ofp &= ~UF_FIONBIO_ON; 134549329Shibler /* 134663726Shibler * Only set/clear if O_NONBLOCK/FNDELAY not in effect 134749329Shibler */ 134863726Shibler if ((*ofp & (UF_NONBLOCK_ON|UF_FNDELAY_ON)) == 0) { 134963726Shibler tmp = *ofp & UF_FIONBIO_ON; 135049329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 135149329Shibler (caddr_t)&tmp, p); 135249329Shibler } 135349329Shibler break; 135449329Shibler } 135549329Shibler 135641486Smckusick case HPUXTIOCCONS: 135741486Smckusick *(int *)data = 1; 135848478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 135941486Smckusick break; 136041486Smckusick 136141486Smckusick /* BSD-style job control ioctls */ 136241486Smckusick case HPUXTIOCLBIS: 136341486Smckusick case HPUXTIOCLBIC: 136441486Smckusick case HPUXTIOCLSET: 136541486Smckusick *(int *)data &= HPUXLTOSTOP; 136641486Smckusick if (*(int *)data & HPUXLTOSTOP) 136741486Smckusick *(int *)data = LTOSTOP; 136841486Smckusick /* fall into */ 136964478Shibler 137064478Shibler /* simple mapping cases */ 137141486Smckusick case HPUXTIOCLGET: 137241486Smckusick case HPUXTIOCSLTC: 137341486Smckusick case HPUXTIOCGLTC: 137441486Smckusick case HPUXTIOCSPGRP: 137541486Smckusick case HPUXTIOCGPGRP: 137664478Shibler case HPUXTIOCGWINSZ: 137764478Shibler case HPUXTIOCSWINSZ: 137848478Skarels error = (*fp->f_ops->fo_ioctl) 137948478Skarels (fp, hpuxtobsdioctl(com), data, p); 138043452Shibler if (error == 0 && com == HPUXTIOCLGET) { 138141486Smckusick *(int *)data &= LTOSTOP; 138241486Smckusick if (*(int *)data & LTOSTOP) 138341486Smckusick *(int *)data = HPUXLTOSTOP; 138441486Smckusick } 138541486Smckusick break; 138641486Smckusick 138755832Shibler /* SYS 5 termio and POSIX termios */ 138841486Smckusick case HPUXTCGETA: 138941486Smckusick case HPUXTCSETA: 139041486Smckusick case HPUXTCSETAW: 139141486Smckusick case HPUXTCSETAF: 139255832Shibler case HPUXTCGETATTR: 139355832Shibler case HPUXTCSETATTR: 139455832Shibler case HPUXTCSETATTRD: 139555832Shibler case HPUXTCSETATTRF: 139664478Shibler error = hpuxtermio(uap->fdes, com, data, p); 139741486Smckusick break; 139841486Smckusick 139941486Smckusick default: 140048478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 140141486Smckusick break; 140241486Smckusick } 140341486Smckusick /* 140441486Smckusick * Copy any data to user, size was 140541486Smckusick * already set and checked above. 140641486Smckusick */ 140743452Shibler if (error == 0 && (com&IOC_OUT) && size) 140843452Shibler error = copyout(data, uap->cmarg, (u_int)size); 140941486Smckusick if (memp) 141041486Smckusick free(memp, M_IOCTLOPS); 141144421Skarels return (error); 141241486Smckusick } 141341486Smckusick 141441486Smckusick /* 141541486Smckusick * Man page lies, behaviour here is based on observed behaviour. 141641486Smckusick */ 141754917Storek struct hpuxgetcontext_args { 141854917Storek char *buf; 141954917Storek int len; 142054917Storek }; 142143452Shibler hpuxgetcontext(p, uap, retval) 142243452Shibler struct proc *p; 142354917Storek struct hpuxgetcontext_args *uap; 142443452Shibler int *retval; 142543452Shibler { 142641486Smckusick int error = 0; 142741486Smckusick register int len; 142841486Smckusick 142953922Shibler #if defined(HP380) 143053922Shibler if (machineid == HP_380) { 143155072Spendry len = min(uap->len, sizeof(hpux040context)); 143253922Shibler if (len) 143353922Shibler error = copyout(hpux040context, uap->buf, len); 143453922Shibler if (error == 0) 143553922Shibler *retval = sizeof(hpux040context); 143653922Shibler return (error); 143753922Shibler } 143853922Shibler #endif 143955072Spendry len = min(uap->len, sizeof(hpuxcontext)); 144041486Smckusick if (len) 144141486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 144243452Shibler if (error == 0) 144343452Shibler *retval = sizeof(hpuxcontext); 144444421Skarels return (error); 144541486Smckusick } 144641486Smckusick 144741486Smckusick /* 144841486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 144941486Smckusick * Note we do not check the real uid or "saved" uid. 145041486Smckusick */ 145154917Storek struct hpuxgetpgrp2_args { 145254917Storek int pid; 145354917Storek }; 145443452Shibler hpuxgetpgrp2(cp, uap, retval) 145543452Shibler struct proc *cp; 145654917Storek register struct hpuxgetpgrp2_args *uap; 145743452Shibler int *retval; 145841486Smckusick { 145941486Smckusick register struct proc *p; 146041486Smckusick 146141486Smckusick if (uap->pid == 0) 146243452Shibler uap->pid = cp->p_pid; 146341486Smckusick p = pfind(uap->pid); 146443452Shibler if (p == 0) 146544421Skarels return (ESRCH); 146648478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 146748478Skarels !inferior(p)) 146844421Skarels return (EPERM); 146943452Shibler *retval = p->p_pgid; 147044421Skarels return (0); 147141486Smckusick } 147241486Smckusick 147341486Smckusick /* 147441486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 147541486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 147641486Smckusick */ 147754917Storek struct hpuxsetpgrp2_args { 147854917Storek int pid; 147954917Storek int pgrp; 148054917Storek }; 148143452Shibler hpuxsetpgrp2(p, uap, retval) 148243452Shibler struct proc *p; 148354917Storek struct hpuxsetpgrp2_args *uap; 148443452Shibler int *retval; 148543452Shibler { 148641486Smckusick /* empirically determined */ 148743452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 148844421Skarels return (EINVAL); 148948478Skarels return (setpgid(p, uap, retval)); 149041486Smckusick } 149141486Smckusick 149241486Smckusick /* 149355165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 149445753Smckusick */ 149554917Storek struct hpuxsetresuid_args { 149654917Storek int ruid; 149754917Storek int euid; 149854917Storek int suid; 149954917Storek }; 150045753Smckusick hpuxsetresuid(p, uap, retval) 150155165Smckusick struct proc *p; 150254917Storek struct hpuxsetresuid_args *uap; 150345753Smckusick int *retval; 150445753Smckusick { 150555165Smckusick return (osetreuid(p, uap, retval)); 150645753Smckusick } 150745753Smckusick 150854917Storek struct hpuxsetresgid_args { 150954917Storek int rgid; 151054917Storek int egid; 151154917Storek int sgid; 151254917Storek }; 151345753Smckusick hpuxsetresgid(p, uap, retval) 151455165Smckusick struct proc *p; 151554917Storek struct hpuxsetresgid_args *uap; 151645753Smckusick int *retval; 151745753Smckusick { 151855165Smckusick return (osetregid(p, uap, retval)); 151945753Smckusick } 152045753Smckusick 152157307Shibler struct hpuxrlimit_args { 152257307Shibler u_int which; 152357307Shibler struct orlimit *rlp; 152457307Shibler }; 152557307Shibler hpuxgetrlimit(p, uap, retval) 152657307Shibler struct proc *p; 152757307Shibler struct hpuxrlimit_args *uap; 152857307Shibler int *retval; 152957307Shibler { 153057307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 153157307Shibler return (EINVAL); 153257307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 153357307Shibler uap->which = RLIMIT_NOFILE; 153460110Smckusick return (ogetrlimit(p, uap, retval)); 153557307Shibler } 153657307Shibler 153757307Shibler hpuxsetrlimit(p, uap, retval) 153857307Shibler struct proc *p; 153957307Shibler struct hpuxrlimit_args *uap; 154057307Shibler int *retval; 154157307Shibler { 154257307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 154357307Shibler return (EINVAL); 154457307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 154557307Shibler uap->which = RLIMIT_NOFILE; 154660110Smckusick return (osetrlimit(p, uap, retval)); 154757307Shibler } 154857307Shibler 154945753Smckusick /* 155045753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 155145753Smckusick */ 155254917Storek struct hpuxlockf_args { 155354917Storek int fd; 155454917Storek int func; 155554917Storek long size; 155654917Storek }; 155745753Smckusick hpuxlockf(p, uap, retval) 155845753Smckusick struct proc *p; 155954917Storek struct hpuxlockf_args *uap; 156045753Smckusick int *retval; 156145753Smckusick { 156245753Smckusick return (0); 156345753Smckusick } 156445753Smckusick 156554917Storek struct hpuxgetaccess_args { 156654917Storek char *path; 156754917Storek int uid; 156854917Storek int ngroups; 156954917Storek int *gidset; 157054917Storek void *label; 157154917Storek void *privs; 157254917Storek }; 157345753Smckusick hpuxgetaccess(p, uap, retval) 157445753Smckusick register struct proc *p; 157554917Storek register struct hpuxgetaccess_args *uap; 157645753Smckusick int *retval; 157745753Smckusick { 157845753Smckusick int lgroups[NGROUPS]; 157945753Smckusick int error = 0; 158045753Smckusick register struct ucred *cred; 158145753Smckusick register struct vnode *vp; 158252330Smckusick struct nameidata nd; 158345753Smckusick 158445753Smckusick /* 158545753Smckusick * Build an appropriate credential structure 158645753Smckusick */ 158748478Skarels cred = crdup(p->p_ucred); 158845753Smckusick switch (uap->uid) { 158945753Smckusick case 65502: /* UID_EUID */ 159045753Smckusick break; 159145753Smckusick case 65503: /* UID_RUID */ 159248478Skarels cred->cr_uid = p->p_cred->p_ruid; 159345753Smckusick break; 159445753Smckusick case 65504: /* UID_SUID */ 159545753Smckusick error = EINVAL; 159645753Smckusick break; 159745753Smckusick default: 159845753Smckusick if (uap->uid > 65504) 159945753Smckusick error = EINVAL; 160045753Smckusick cred->cr_uid = uap->uid; 160145753Smckusick break; 160245753Smckusick } 160345753Smckusick switch (uap->ngroups) { 160445753Smckusick case -1: /* NGROUPS_EGID */ 160545753Smckusick cred->cr_ngroups = 1; 160645753Smckusick break; 160745753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 160845753Smckusick break; 160945753Smckusick case -2: /* NGROUPS_RGID */ 161045753Smckusick cred->cr_ngroups = 1; 161148478Skarels cred->cr_gid = p->p_cred->p_rgid; 161245753Smckusick break; 161345753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 161448478Skarels cred->cr_gid = p->p_cred->p_rgid; 161545753Smckusick break; 161645753Smckusick case -3: /* NGROUPS_SGID */ 161745753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 161845753Smckusick error = EINVAL; 161945753Smckusick break; 162045753Smckusick case -4: /* NGROUPS_SUPP */ 162145753Smckusick if (cred->cr_ngroups > 1) 162245753Smckusick cred->cr_gid = cred->cr_groups[1]; 162345753Smckusick else 162445753Smckusick error = EINVAL; 162545753Smckusick break; 162645753Smckusick default: 162745753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 162845753Smckusick error = copyin((caddr_t)uap->gidset, 162945753Smckusick (caddr_t)&lgroups[0], 163045753Smckusick uap->ngroups * sizeof(lgroups[0])); 163145753Smckusick else 163245753Smckusick error = EINVAL; 163345753Smckusick if (error == 0) { 163445753Smckusick int gid; 163545753Smckusick 163645753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 163745753Smckusick cred->cr_groups[gid] = lgroups[gid]; 163845753Smckusick cred->cr_ngroups = uap->ngroups; 163945753Smckusick } 164045753Smckusick break; 164145753Smckusick } 164245753Smckusick /* 164345753Smckusick * Lookup file using caller's effective IDs. 164445753Smckusick */ 164545753Smckusick if (error == 0) { 164652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 164752330Smckusick uap->path, p); 164852330Smckusick error = namei(&nd); 164945753Smckusick } 165045753Smckusick if (error) { 165145753Smckusick crfree(cred); 165245753Smckusick return (error); 165345753Smckusick } 165445753Smckusick /* 165545753Smckusick * Use the constructed credentials for access checks. 165645753Smckusick */ 165752330Smckusick vp = nd.ni_vp; 165845753Smckusick *retval = 0; 165948478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 166045753Smckusick *retval |= R_OK; 166148478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 166245753Smckusick *retval |= W_OK; 166345753Smckusick /* XXX we return X_OK for root on VREG even if not */ 166448478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 166545753Smckusick *retval |= X_OK; 166645753Smckusick vput(vp); 166745753Smckusick crfree(cred); 166845753Smckusick return (error); 166945753Smckusick } 167045753Smckusick 167149134Skarels extern char kstack[]; 167241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 167341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 167441486Smckusick 167541486Smckusick /* simplified FP structure */ 167641486Smckusick struct bsdfp { 167741486Smckusick int save[54]; 167841486Smckusick int reg[24]; 167941486Smckusick int ctrl[3]; 168041486Smckusick }; 168141486Smckusick 168257307Shibler /* 168357307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 168457307Shibler */ 168557307Shibler hpuxtobsduoff(off, isps, p) 168657307Shibler int *off, *isps; 168757307Shibler struct proc *p; 168841486Smckusick { 168957307Shibler register int *ar0 = p->p_md.md_regs; 169041486Smckusick struct hpuxfp *hp; 169141486Smckusick struct bsdfp *bp; 169241486Smckusick register u_int raddr; 169341486Smckusick 169457307Shibler *isps = 0; 169557307Shibler 169648478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 169741486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 169848478Skarels return(UOFF(U_ar0)); 169941486Smckusick 170041486Smckusick #ifdef FPCOPROC 170157307Shibler /* FP registers from PCB */ 170241486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 170341486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 170441486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 170541486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 170641486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 170741486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 170841486Smckusick #endif 170941486Smckusick 171041486Smckusick /* 171141486Smckusick * Everything else we recognize comes from the kernel stack, 171241486Smckusick * so we convert off to an absolute address (if not already) 171341486Smckusick * for simplicity. 171441486Smckusick */ 171541486Smckusick if (off < (int *)ctob(UPAGES)) 171649134Skarels off = (int *)((u_int)off + (u_int)kstack); 171741486Smckusick 171841486Smckusick /* 171957307Shibler * General registers. 172054857Shibler * We know that the HP-UX registers are in the same order as ours. 172141486Smckusick * The only difference is that their PS is 2 bytes instead of a 172241486Smckusick * padded 4 like ours throwing the alignment off. 172341486Smckusick */ 172448478Skarels if (off >= ar0 && off < &ar0[18]) { 172541486Smckusick /* 172641486Smckusick * PS: return low word and high word of PC as HP-UX would 172741486Smckusick * (e.g. &u.u_ar0[16.5]). 172857307Shibler * 172957307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 173057307Shibler * it and passing such an offset to procxmt will cause 173157307Shibler * it to fail anyway. Instead, we just set the offset 173257307Shibler * to PS and let hpuxptrace() shift up the value returned. 173341486Smckusick */ 173457307Shibler if (off == &ar0[PS]) { 173557307Shibler #if 0 173648478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 173757307Shibler #else 173857307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 173957307Shibler #endif 174057307Shibler *isps = 1; 174157307Shibler } 174241486Smckusick /* 174357307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 174457307Shibler * is only 16 bits. 174541486Smckusick */ 174648478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 174748478Skarels raddr = (u_int) &ar0[PC]; 174841486Smckusick /* 174941486Smckusick * D0-D7, A0-A7: easy 175041486Smckusick */ 175141486Smckusick else 175248478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 175349134Skarels return((int)(raddr - (u_int)kstack)); 175441486Smckusick } 175541486Smckusick 175641486Smckusick /* everything else */ 175741486Smckusick return(-1); 175841486Smckusick } 175941486Smckusick 176041486Smckusick /* 176154857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 176241486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 176341486Smckusick * convert the entire user struct. 176441486Smckusick */ 176541486Smckusick hpuxdumpu(vp, cred) 176641486Smckusick struct vnode *vp; 176741486Smckusick struct ucred *cred; 176841486Smckusick { 176948478Skarels struct proc *p = curproc; 177041486Smckusick int error; 177141486Smckusick struct hpuxuser *faku; 177241486Smckusick struct bsdfp *bp; 177341486Smckusick short *foop; 177441486Smckusick 177541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 177641486Smckusick /* 177741486Smckusick * Make sure there is no mistake about this 177841486Smckusick * being a real user structure. 177941486Smckusick */ 178041486Smckusick bzero((caddr_t)faku, ctob(1)); 178141486Smckusick /* 178241486Smckusick * Fill in the process sizes. 178341486Smckusick */ 178448478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 178548478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 178648478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 178741486Smckusick /* 178841486Smckusick * Fill in the exec header for CDB. 178941486Smckusick * This was saved back in exec(). As far as I can tell CDB 179041486Smckusick * only uses this information to verify that a particular 179141486Smckusick * core file goes with a particular binary. 179241486Smckusick */ 179357307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 179441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 179541486Smckusick /* 179641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 179754857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 179841486Smckusick * so we have to move it up. 179941486Smckusick */ 180052381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 180152381Smckusick foop = (short *) p->p_md.md_regs; 180241486Smckusick foop[32] = foop[33]; 180341486Smckusick foop[33] = foop[34]; 180441486Smckusick foop[34] = foop[35]; 180541486Smckusick #ifdef FPCOPROC 180641486Smckusick /* 180754857Shibler * Copy 68881 registers from our PCB format to HP-UX format 180841486Smckusick */ 180949134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 181041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 181141486Smckusick sizeof(bp->save)); 181241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 181341486Smckusick sizeof(bp->ctrl)); 181441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 181541486Smckusick sizeof(bp->reg)); 181641486Smckusick #endif 181741486Smckusick /* 181841486Smckusick * Slay the dragon 181941486Smckusick */ 182041486Smckusick faku->hpuxu_dragon = -1; 182141486Smckusick /* 182241486Smckusick * Dump this artfully constructed page in place of the 182341486Smckusick * user struct page. 182441486Smckusick */ 182548478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 182648478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 182749134Skarels (int *)NULL, p); 182841486Smckusick /* 182941486Smckusick * Dump the remaining UPAGES-1 pages normally 183041486Smckusick */ 183141486Smckusick if (!error) 183249134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 183341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 183449134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 183541486Smckusick free((caddr_t)faku, M_TEMP); 183641486Smckusick return(error); 183741486Smckusick } 183841486Smckusick 183941486Smckusick /* 184041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 184141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 184241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 184341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 184457307Shibler * 184557307Shibler * These are still needed as of HP-UX 7.05. 184641486Smckusick */ 184755832Shibler #ifdef COMPAT_OHPUX 184855832Shibler 184945753Smckusick #define HPUX_HZ 50 185045753Smckusick 185157307Shibler #include "sys/times.h" 185241486Smckusick 185341486Smckusick /* from old timeb.h */ 185441486Smckusick struct hpuxtimeb { 185541486Smckusick time_t time; 185641486Smckusick u_short millitm; 185741486Smckusick short timezone; 185841486Smckusick short dstflag; 185941486Smckusick }; 186041486Smckusick 186141486Smckusick /* ye ole stat structure */ 186241486Smckusick struct ohpuxstat { 186353481Smckusick u_short ohst_dev; 186441486Smckusick u_short ohst_ino; 186541486Smckusick u_short ohst_mode; 186641486Smckusick short ohst_nlink; 186741486Smckusick short ohst_uid; 186841486Smckusick short ohst_gid; 186953481Smckusick u_short ohst_rdev; 187041486Smckusick int ohst_size; 187141486Smckusick int ohst_atime; 187241486Smckusick int ohst_mtime; 187341486Smckusick int ohst_ctime; 187441486Smckusick }; 187541486Smckusick 187641486Smckusick /* 187741486Smckusick * SYS V style setpgrp() 187841486Smckusick */ 187943452Shibler ohpuxsetpgrp(p, uap, retval) 188043452Shibler register struct proc *p; 188143452Shibler int *uap, *retval; 188241486Smckusick { 188341486Smckusick if (p->p_pid != p->p_pgid) 188448478Skarels enterpgrp(p, p->p_pid, 0); 188543452Shibler *retval = p->p_pgid; 188645753Smckusick return (0); 188741486Smckusick } 188841486Smckusick 188954917Storek struct ohpuxtime_args { 189054917Storek long *tp; 189154917Storek }; 189243452Shibler ohpuxtime(p, uap, retval) 189343452Shibler struct proc *p; 189454917Storek register struct ohpuxtime_args *uap; 189554917Storek int *retval; 189641486Smckusick { 189745753Smckusick int error = 0; 189841486Smckusick 189941486Smckusick if (uap->tp) 190043452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 190143452Shibler sizeof (long)); 190254917Storek *(time_t *)retval = time.tv_sec; 190344421Skarels return (error); 190441486Smckusick } 190541486Smckusick 190654917Storek struct ohpuxstime_args { 190754917Storek int time; 190854917Storek }; 190943452Shibler ohpuxstime(p, uap, retval) 191043452Shibler struct proc *p; 191154917Storek register struct ohpuxstime_args *uap; 191243452Shibler int *retval; 191341486Smckusick { 191441486Smckusick struct timeval tv; 191543452Shibler int s, error; 191641486Smckusick 191741486Smckusick tv.tv_sec = uap->time; 191841486Smckusick tv.tv_usec = 0; 191948478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 192044421Skarels return (error); 192141486Smckusick 192241486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 192341486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 192441486Smckusick s = splhigh(); time = tv; splx(s); 192541486Smckusick resettodr(); 192644421Skarels return (0); 192741486Smckusick } 192841486Smckusick 192954917Storek struct ohpuxftime_args { 193054917Storek struct hpuxtimeb *tp; 193154917Storek }; 193243452Shibler ohpuxftime(p, uap, retval) 193343452Shibler struct proc *p; 193454917Storek register struct ohpuxftime_args *uap; 193543452Shibler int *retval; 193643452Shibler { 193741486Smckusick struct hpuxtimeb tb; 193841486Smckusick int s; 193941486Smckusick 194041486Smckusick s = splhigh(); 194141486Smckusick tb.time = time.tv_sec; 194241486Smckusick tb.millitm = time.tv_usec / 1000; 194341486Smckusick splx(s); 194441486Smckusick tb.timezone = tz.tz_minuteswest; 194541486Smckusick tb.dstflag = tz.tz_dsttime; 194644421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 194741486Smckusick } 194841486Smckusick 194954917Storek struct ohpuxalarm_args { 195054917Storek int deltat; 195154917Storek }; 195243452Shibler ohpuxalarm(p, uap, retval) 195343452Shibler register struct proc *p; 195454917Storek register struct ohpuxalarm_args *uap; 195543452Shibler int *retval; 195641486Smckusick { 195741486Smckusick int s = splhigh(); 195841486Smckusick 195941486Smckusick untimeout(realitexpire, (caddr_t)p); 196041486Smckusick timerclear(&p->p_realtimer.it_interval); 196143452Shibler *retval = 0; 196241486Smckusick if (timerisset(&p->p_realtimer.it_value) && 196341486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 196443452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 196541486Smckusick if (uap->deltat == 0) { 196641486Smckusick timerclear(&p->p_realtimer.it_value); 196741486Smckusick splx(s); 196844421Skarels return (0); 196941486Smckusick } 197041486Smckusick p->p_realtimer.it_value = time; 197141486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 197241486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 197341486Smckusick splx(s); 197444421Skarels return (0); 197541486Smckusick } 197641486Smckusick 197754917Storek struct ohpuxnice_args { 197854917Storek int niceness; 197954917Storek }; 198043452Shibler ohpuxnice(p, uap, retval) 198143452Shibler register struct proc *p; 198254917Storek register struct ohpuxnice_args *uap; 198343452Shibler int *retval; 198441486Smckusick { 198543452Shibler int error; 198641486Smckusick 198743452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 198843452Shibler if (error == 0) 198943452Shibler *retval = p->p_nice - NZERO; 199044421Skarels return (error); 199141486Smckusick } 199241486Smckusick 199354917Storek struct ohpuxtimes_args { 199454917Storek struct tms *tmsb; 199554917Storek }; 199643452Shibler ohpuxtimes(p, uap, retval) 199743452Shibler struct proc *p; 199854917Storek register struct ohpuxtimes_args *uap; 199954917Storek int *retval; 200041486Smckusick { 200154771Storek struct timeval ru, rs; 200241486Smckusick struct tms atms; 200343452Shibler int error; 200441486Smckusick 200554771Storek calcru(p, &ru, &rs, NULL); 200654771Storek atms.tms_utime = hpuxscale(&ru); 200754771Storek atms.tms_stime = hpuxscale(&rs); 200848478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 200948478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 201043452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 201143452Shibler if (error == 0) 201254917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 201344421Skarels return (error); 201441486Smckusick } 201541486Smckusick 201645753Smckusick /* 201745753Smckusick * Doesn't exactly do what the documentation says. 201845753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 201945753Smckusick * is what HP-UX returns. 202045753Smckusick */ 202145753Smckusick hpuxscale(tvp) 202241486Smckusick register struct timeval *tvp; 202341486Smckusick { 202445753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 202541486Smckusick } 202641486Smckusick 202741486Smckusick /* 202841486Smckusick * Set IUPD and IACC times on file. 202941486Smckusick * Can't set ICHG. 203041486Smckusick */ 203154917Storek struct ohpuxutime_args { 203254917Storek char *fname; 203354917Storek time_t *tptr; 203454917Storek }; 203543452Shibler ohpuxutime(p, uap, retval) 203643452Shibler struct proc *p; 203754917Storek register struct ohpuxutime_args *uap; 203843452Shibler int *retval; 203943452Shibler { 204048478Skarels register struct vnode *vp; 204141486Smckusick struct vattr vattr; 204241486Smckusick time_t tv[2]; 204343452Shibler int error; 204448478Skarels struct nameidata nd; 204541486Smckusick 204641486Smckusick if (uap->tptr) { 204743452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 204843452Shibler if (error) 204944421Skarels return (error); 205041486Smckusick } else 205141486Smckusick tv[0] = tv[1] = time.tv_sec; 205241486Smckusick vattr_null(&vattr); 205354107Smckusick vattr.va_atime.ts_sec = tv[0]; 205454107Smckusick vattr.va_atime.ts_nsec = 0; 205554107Smckusick vattr.va_mtime.ts_sec = tv[1]; 205654107Smckusick vattr.va_mtime.ts_nsec = 0; 205752330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 205852330Smckusick if (error = namei(&nd)) 205944421Skarels return (error); 206052330Smckusick vp = nd.ni_vp; 206142154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 206243452Shibler error = EROFS; 206341486Smckusick else 206452330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 206541486Smckusick vput(vp); 206644421Skarels return (error); 206741486Smckusick } 206841486Smckusick 206943452Shibler ohpuxpause(p, uap, retval) 207043452Shibler struct proc *p; 207143452Shibler int *uap, *retval; 207241486Smckusick { 207349134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 207442155Skarels /* always return EINTR rather than ERESTART... */ 207544421Skarels return (EINTR); 207641486Smckusick } 207741486Smckusick 207841486Smckusick /* 207941486Smckusick * The old fstat system call. 208041486Smckusick */ 208154917Storek struct ohpuxfstat_args { 208254917Storek int fd; 208354917Storek struct ohpuxstat *sb; 208454917Storek }; 208543452Shibler ohpuxfstat(p, uap, retval) 208643452Shibler struct proc *p; 208754917Storek register struct ohpuxfstat_args *uap; 208843452Shibler int *retval; 208943452Shibler { 209045923Smckusick register struct filedesc *fdp = p->p_fd; 209141486Smckusick struct file *fp; 209241486Smckusick 209348478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 209448478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 209544421Skarels return (EBADF); 209643452Shibler if (fp->f_type != DTYPE_VNODE) 209744421Skarels return (EINVAL); 209855282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 209941486Smckusick } 210041486Smckusick 210141486Smckusick /* 210241486Smckusick * Old stat system call. This version follows links. 210341486Smckusick */ 210454917Storek struct ohpuxstat_args { 210554917Storek char *fname; 210654917Storek struct ohpuxstat *sb; 210754917Storek }; 210843452Shibler ohpuxstat(p, uap, retval) 210943452Shibler struct proc *p; 211054917Storek register struct ohpuxstat_args *uap; 211143452Shibler int *retval; 211243452Shibler { 211343452Shibler int error; 211448478Skarels struct nameidata nd; 211541486Smckusick 211652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 211752330Smckusick if (error = namei(&nd)) 211844421Skarels return (error); 211955282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 212052330Smckusick vput(nd.ni_vp); 212144421Skarels return (error); 212241486Smckusick } 212341486Smckusick 212441486Smckusick int 212555282Smckusick ohpuxstat1(vp, ub, p) 212657307Shibler struct vnode *vp; 212741486Smckusick struct ohpuxstat *ub; 212855282Smckusick struct proc *p; 212941486Smckusick { 213057307Shibler struct ohpuxstat ohsb; 213157307Shibler struct stat sb; 213257307Shibler int error; 213341486Smckusick 213457307Shibler error = vn_stat(vp, &sb, p); 213541486Smckusick if (error) 213657307Shibler return (error); 213757307Shibler 213857307Shibler ohsb.ohst_dev = sb.st_dev; 213957307Shibler ohsb.ohst_ino = sb.st_ino; 214057307Shibler ohsb.ohst_mode = sb.st_mode; 214157307Shibler ohsb.ohst_nlink = sb.st_nlink; 214257307Shibler ohsb.ohst_uid = sb.st_uid; 214357307Shibler ohsb.ohst_gid = sb.st_gid; 214457307Shibler ohsb.ohst_rdev = sb.st_rdev; 214557307Shibler if (sb.st_size < (quad_t)1 << 32) 214657307Shibler ohsb.ohst_size = sb.st_size; 214757307Shibler else 214857307Shibler ohsb.ohst_size = -2; 214957307Shibler ohsb.ohst_atime = sb.st_atime; 215057307Shibler ohsb.ohst_mtime = sb.st_mtime; 215157307Shibler ohsb.ohst_ctime = sb.st_ctime; 215257307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 215341486Smckusick } 215441486Smckusick #endif 215555832Shibler #endif 2156