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 * 12*64478Shibler * from: Utah $Hdr: hpux_compat.c 1.64 93/08/05$ 1341486Smckusick * 14*64478Shibler * @(#)hpux_compat.c 8.2 (Berkeley) 09/09/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 80*64478Shibler #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, 92*64478Shibler /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46, 251,BERR, 93*64478Shibler /*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 128*64478Shibler /* 129*64478Shibler * HP-UX fork and vfork need to map the EAGAIN return value appropriately. 130*64478Shibler */ 131*64478Shibler hpuxfork(p, uap, retval) 132*64478Shibler struct proc *p; 133*64478Shibler struct hpuxwait3_args *uap; 134*64478Shibler int *retval; 135*64478Shibler { 136*64478Shibler int error; 137*64478Shibler 138*64478Shibler error = fork(p, uap, retval); 139*64478Shibler if (error == EAGAIN) 140*64478Shibler error = OEAGAIN; 141*64478Shibler return (error); 142*64478Shibler } 143*64478Shibler 144*64478Shibler hpuxvfork(p, uap, retval) 145*64478Shibler struct proc *p; 146*64478Shibler struct hpuxwait3_args *uap; 147*64478Shibler int *retval; 148*64478Shibler 149*64478Shibler { 150*64478Shibler int error; 151*64478Shibler 152*64478Shibler error = vfork(p, uap, retval); 153*64478Shibler if (error == EAGAIN) 154*64478Shibler error = OEAGAIN; 155*64478Shibler return (error); 156*64478Shibler } 157*64478Shibler 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; 381*64478Shibler 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) 405*64478Shibler *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; 443*64478Shibler 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; 465*64478Shibler 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; 487*64478Shibler 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; 509*64478Shibler 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 63853922Shibler /* open files */ 63953922Shibler case HPUX_SYSCONF_OPENMAX: 64053922Shibler *retval = NOFILE; 64153922Shibler break; 64253922Shibler 64353922Shibler /* architecture */ 64453922Shibler case HPUX_SYSCONF_CPUTYPE: 64553922Shibler switch (machineid) { 64653922Shibler case HP_320: 64753922Shibler case HP_330: 64853922Shibler case HP_350: 64953922Shibler *retval = HPUX_SYSCONF_CPUM020; 65053922Shibler break; 65153922Shibler case HP_340: 65253922Shibler case HP_360: 65353922Shibler case HP_370: 65453922Shibler case HP_375: 65553922Shibler *retval = HPUX_SYSCONF_CPUM030; 65653922Shibler break; 65753922Shibler case HP_380: 65857307Shibler case HP_433: 65953922Shibler *retval = HPUX_SYSCONF_CPUM040; 66053922Shibler break; 66153922Shibler } 66253922Shibler break; 66353922Shibler default: 66454857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 66553922Shibler return (EINVAL); 66653922Shibler } 66753922Shibler return (0); 66853922Shibler } 66953922Shibler 67054917Storek struct hpuxstat_args { 67154917Storek char *fname; 67254917Storek struct hpuxstat *hsb; 67354917Storek }; 67443452Shibler hpuxstat(p, uap, retval) 67543452Shibler struct proc *p; 67654917Storek struct hpuxstat_args *uap; 67743452Shibler int *retval; 67843452Shibler { 67955282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 68041486Smckusick } 68141486Smckusick 68254917Storek struct hpuxlstat_args { 68354917Storek char *fname; 68454917Storek struct hpuxstat *hsb; 68554917Storek }; 68643452Shibler hpuxlstat(p, uap, retval) 68743452Shibler struct proc *p; 68854917Storek struct hpuxlstat_args *uap; 68943452Shibler int *retval; 69041486Smckusick { 69155282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 69241486Smckusick } 69341486Smckusick 69454917Storek struct hpuxfstat_args { 69554917Storek int fdes; 69654917Storek struct hpuxstat *hsb; 69754917Storek }; 69843452Shibler hpuxfstat(p, uap, retval) 69943452Shibler struct proc *p; 70054917Storek register struct hpuxfstat_args *uap; 70143452Shibler int *retval; 70241486Smckusick { 70345923Smckusick register struct filedesc *fdp = p->p_fd; 70441486Smckusick register struct file *fp; 70541486Smckusick struct stat sb; 70643452Shibler int error; 70741486Smckusick 70848478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 70948478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 71044421Skarels return (EBADF); 71143452Shibler 71241486Smckusick switch (fp->f_type) { 71341486Smckusick 71441486Smckusick case DTYPE_VNODE: 71555282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 71641486Smckusick break; 71741486Smckusick 71841486Smckusick case DTYPE_SOCKET: 71955282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 72041486Smckusick break; 72141486Smckusick 72241486Smckusick default: 72341486Smckusick panic("fstat"); 72441486Smckusick /*NOTREACHED*/ 72541486Smckusick } 72641486Smckusick /* is this right for sockets?? */ 72743452Shibler if (error == 0) 72843452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 72944421Skarels return (error); 73041486Smckusick } 73141486Smckusick 73254917Storek struct hpuxulimit_args { 73354917Storek int cmd; 73454917Storek long newlimit; 73554917Storek }; 73643452Shibler hpuxulimit(p, uap, retval) 73743452Shibler struct proc *p; 73854917Storek register struct hpuxulimit_args *uap; 73953481Smckusick long *retval; 74043452Shibler { 74141486Smckusick struct rlimit *limp; 74243452Shibler int error = 0; 74341486Smckusick 74448478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 74541486Smckusick switch (uap->cmd) { 74641486Smckusick case 2: 74741486Smckusick uap->newlimit *= 512; 74841486Smckusick if (uap->newlimit > limp->rlim_max && 74948478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 75041486Smckusick break; 75141486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 75241486Smckusick /* else fall into... */ 75341486Smckusick 75441486Smckusick case 1: 75545753Smckusick *retval = limp->rlim_max / 512; 75641486Smckusick break; 75741486Smckusick 75841486Smckusick case 3: 75948478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 76048478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 76141486Smckusick break; 76241486Smckusick 76341486Smckusick default: 76443452Shibler error = EINVAL; 76541486Smckusick break; 76641486Smckusick } 76744421Skarels return (error); 76841486Smckusick } 76941486Smckusick 77041486Smckusick /* 77141486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 77241486Smckusick * values -16 (high) thru -1 (low). 77341486Smckusick */ 77454917Storek struct hpuxrtprio_args { 77554917Storek int pid; 77654917Storek int prio; 77754917Storek }; 77843452Shibler hpuxrtprio(cp, uap, retval) 77943452Shibler struct proc *cp; 78054917Storek register struct hpuxrtprio_args *uap; 78143452Shibler int *retval; 78243452Shibler { 78341486Smckusick struct proc *p; 78443452Shibler int nice, error; 78541486Smckusick 78641486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 78743452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 78844421Skarels return (EINVAL); 78941486Smckusick if (uap->pid == 0) 79043452Shibler p = cp; 79143452Shibler else if ((p = pfind(uap->pid)) == 0) 79244421Skarels return (ESRCH); 79341486Smckusick nice = p->p_nice; 79441486Smckusick if (nice < NZERO) 79543452Shibler *retval = (nice + 16) << 3; 79641486Smckusick else 79743452Shibler *retval = RTPRIO_RTOFF; 79841486Smckusick switch (uap->prio) { 79941486Smckusick 80041486Smckusick case RTPRIO_NOCHG: 80144421Skarels return (0); 80241486Smckusick 80341486Smckusick case RTPRIO_RTOFF: 80441486Smckusick if (nice >= NZERO) 80544421Skarels return (0); 80641486Smckusick nice = NZERO; 80741486Smckusick break; 80841486Smckusick 80941486Smckusick default: 81041486Smckusick nice = (uap->prio >> 3) - 16; 81141486Smckusick break; 81241486Smckusick } 81343452Shibler error = donice(cp, p, nice); 81443452Shibler if (error == EACCES) 81543452Shibler error = EPERM; 81644421Skarels return (error); 81741486Smckusick } 81841486Smckusick 81954917Storek struct hpuxadvise_args { 82054917Storek int arg; 82154917Storek }; 82243452Shibler hpuxadvise(p, uap, retval) 82343452Shibler struct proc *p; 82454917Storek struct hpuxadvise_args *uap; 82543452Shibler int *retval; 82641486Smckusick { 82743452Shibler int error = 0; 82841486Smckusick 82941486Smckusick switch (uap->arg) { 83041486Smckusick case 0: 83157307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 83241486Smckusick break; 83341486Smckusick case 1: 83441486Smckusick ICIA(); 83541486Smckusick break; 83641486Smckusick case 2: 83741486Smckusick DCIA(); 83841486Smckusick break; 83941486Smckusick default: 84043452Shibler error = EINVAL; 84141486Smckusick break; 84241486Smckusick } 84344421Skarels return (error); 84441486Smckusick } 84541486Smckusick 84654917Storek struct hpuxptrace_args { 84754917Storek int req; 84854917Storek int pid; 84954917Storek int *addr; 85054917Storek int data; 85154917Storek }; 85243452Shibler hpuxptrace(p, uap, retval) 85343452Shibler struct proc *p; 85454917Storek struct hpuxptrace_args *uap; 85543452Shibler int *retval; 85643452Shibler { 85757307Shibler int error, isps = 0; 85857307Shibler struct proc *cp; 85941486Smckusick 86057307Shibler switch (uap->req) { 86157307Shibler /* map signal */ 86257307Shibler case PT_STEP: 86357307Shibler case PT_CONTINUE: 86441486Smckusick if (uap->data) { 86541486Smckusick uap->data = hpuxtobsdsig(uap->data); 86641486Smckusick if (uap->data == 0) 86741486Smckusick uap->data = NSIG; 86841486Smckusick } 86957307Shibler break; 87057307Shibler /* map u-area offset */ 87157307Shibler case PT_READ_U: 87257307Shibler case PT_WRITE_U: 87357307Shibler /* 87457307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 87557307Shibler * to be called in the child context (procxmt) but we 87657307Shibler * do it here in the parent context to avoid hacks in 87757307Shibler * the MI sys_process.c file. This works only because 87857307Shibler * we can access the child's md_regs pointer and it 87957307Shibler * has the correct value (the child has already trapped 88057307Shibler * into the kernel). 88157307Shibler */ 88257307Shibler if ((cp = pfind(uap->pid)) == 0) 88357307Shibler return (ESRCH); 88457307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 88557307Shibler 88657307Shibler /* 88757307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 88857307Shibler * to write PS actually contain the PS in the high word 88957307Shibler * and the high half of the PC (the following register) 89057307Shibler * in the low word. Move the PS value to where BSD 89157307Shibler * expects it. 89257307Shibler */ 89357307Shibler if (isps && uap->req == PT_WRITE_U) 89457307Shibler uap->data >>= 16; 89557307Shibler break; 89641486Smckusick } 89743452Shibler error = ptrace(p, uap, retval); 89857307Shibler /* 89957307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 90057307Shibler * Note that we do not return the high part of PC like HP-UX 90157307Shibler * would, but the HP-UX debuggers don't require it. 90257307Shibler */ 90357307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 90457307Shibler *retval <<= 16; 90544421Skarels return (error); 90641486Smckusick } 90741486Smckusick 90854917Storek struct hpuxgetdomainname_args { 90954917Storek char *domainname; 91054917Storek u_int len; 91154917Storek }; 91243452Shibler hpuxgetdomainname(p, uap, retval) 91343452Shibler struct proc *p; 91454917Storek register struct hpuxgetdomainname_args *uap; 91543452Shibler int *retval; 91643452Shibler { 91741486Smckusick if (uap->len > domainnamelen + 1) 91841486Smckusick uap->len = domainnamelen + 1; 91944421Skarels return (copyout(domainname, uap->domainname, uap->len)); 92041486Smckusick } 92141486Smckusick 92254917Storek struct hpuxsetdomainname_args { 92354917Storek char *domainname; 92454917Storek u_int len; 92554917Storek }; 92643452Shibler hpuxsetdomainname(p, uap, retval) 92743452Shibler struct proc *p; 92854917Storek register struct hpuxsetdomainname_args *uap; 92943452Shibler int *retval; 93043452Shibler { 93143452Shibler int error; 93241486Smckusick 93348478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 93444421Skarels return (error); 93543452Shibler if (uap->len > sizeof (domainname) - 1) 93644421Skarels return (EINVAL); 93741486Smckusick domainnamelen = uap->len; 93843452Shibler error = copyin(uap->domainname, domainname, uap->len); 93941486Smckusick domainname[domainnamelen] = 0; 94044421Skarels return (error); 94141486Smckusick } 94241486Smckusick 94341486Smckusick #ifdef SYSVSHM 94456506Sbostic #include <sys/shm.h> 94554857Shibler 94643452Shibler hpuxshmat(p, uap, retval) 94743452Shibler struct proc *p; 94843452Shibler int *uap, *retval; 94941486Smckusick { 95044421Skarels return (shmat(p, uap, retval)); 95141486Smckusick } 95241486Smckusick 95343452Shibler hpuxshmdt(p, uap, retval) 95443452Shibler struct proc *p; 95543452Shibler int *uap, *retval; 95641486Smckusick { 95744421Skarels return (shmdt(p, uap, retval)); 95841486Smckusick } 95941486Smckusick 96043452Shibler hpuxshmget(p, uap, retval) 96143452Shibler struct proc *p; 96243452Shibler int *uap, *retval; 96341486Smckusick { 96444421Skarels return (shmget(p, uap, retval)); 96541486Smckusick } 96654857Shibler 967*64478Shibler hpuxshmctl(p, uap, retval) 968*64478Shibler struct proc *p; 969*64478Shibler int *uap, *retval; 970*64478Shibler { 971*64478Shibler return (hpuxshmctl1(p, uap, retval, 0)); 972*64478Shibler } 973*64478Shibler 974*64478Shibler hpuxnshmctl(p, uap, retval) 975*64478Shibler struct proc *p; 976*64478Shibler int *uap, *retval; 977*64478Shibler { 978*64478Shibler return (hpuxshmctl1(p, uap, retval, 1)); 979*64478Shibler } 980*64478Shibler 98154857Shibler /* 98254857Shibler * Handle HP-UX specific commands. 98354857Shibler */ 98454917Storek struct hpuxshmctl_args { 98554917Storek int shmid; 98654917Storek int cmd; 98754917Storek caddr_t buf; 98854917Storek }; 989*64478Shibler hpuxshmctl1(p, uap, retval, isnew) 99054857Shibler struct proc *p; 99154917Storek struct hpuxshmctl_args *uap; 99254857Shibler int *retval; 993*64478Shibler int isnew; 99454857Shibler { 99554857Shibler register struct shmid_ds *shp; 99654857Shibler register struct ucred *cred = p->p_ucred; 997*64478Shibler struct hpuxshmid_ds sbuf; 99854857Shibler int error; 99954857Shibler 100054857Shibler if (error = shmvalid(uap->shmid)) 100154857Shibler return (error); 100254857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 1003*64478Shibler switch (uap->cmd) { 1004*64478Shibler case SHM_LOCK: 1005*64478Shibler case SHM_UNLOCK: 100654857Shibler /* don't really do anything, but make them think we did */ 100754857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 100854857Shibler cred->cr_uid != shp->shm_perm.cuid) 100954857Shibler return (EPERM); 101054857Shibler return (0); 1011*64478Shibler 1012*64478Shibler case IPC_STAT: 1013*64478Shibler if (!isnew) 1014*64478Shibler break; 1015*64478Shibler error = ipcaccess(&shp->shm_perm, IPC_R, cred); 1016*64478Shibler if (error == 0) { 1017*64478Shibler sbuf.shm_perm.uid = shp->shm_perm.uid; 1018*64478Shibler sbuf.shm_perm.gid = shp->shm_perm.gid; 1019*64478Shibler sbuf.shm_perm.cuid = shp->shm_perm.cuid; 1020*64478Shibler sbuf.shm_perm.cgid = shp->shm_perm.cgid; 1021*64478Shibler sbuf.shm_perm.mode = shp->shm_perm.mode; 1022*64478Shibler sbuf.shm_perm.seq = shp->shm_perm.seq; 1023*64478Shibler sbuf.shm_perm.key = shp->shm_perm.key; 1024*64478Shibler sbuf.shm_segsz = shp->shm_segsz; 1025*64478Shibler sbuf.shm_ptbl = shp->shm_handle; /* XXX */ 1026*64478Shibler sbuf.shm_lpid = shp->shm_lpid; 1027*64478Shibler sbuf.shm_cpid = shp->shm_cpid; 1028*64478Shibler sbuf.shm_nattch = shp->shm_nattch; 1029*64478Shibler sbuf.shm_cnattch = shp->shm_nattch; /* XXX */ 1030*64478Shibler sbuf.shm_atime = shp->shm_atime; 1031*64478Shibler sbuf.shm_dtime = shp->shm_dtime; 1032*64478Shibler sbuf.shm_ctime = shp->shm_ctime; 1033*64478Shibler error = copyout((caddr_t)&sbuf, uap->buf, sizeof sbuf); 1034*64478Shibler } 1035*64478Shibler return (error); 1036*64478Shibler 1037*64478Shibler case IPC_SET: 1038*64478Shibler if (!isnew) 1039*64478Shibler break; 1040*64478Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 1041*64478Shibler cred->cr_uid != shp->shm_perm.cuid) { 1042*64478Shibler return (EPERM); 1043*64478Shibler } 1044*64478Shibler error = copyin(uap->buf, (caddr_t)&sbuf, sizeof sbuf); 1045*64478Shibler if (error == 0) { 1046*64478Shibler shp->shm_perm.uid = sbuf.shm_perm.uid; 1047*64478Shibler shp->shm_perm.gid = sbuf.shm_perm.gid; 1048*64478Shibler shp->shm_perm.mode = (shp->shm_perm.mode & ~0777) 1049*64478Shibler | (sbuf.shm_perm.mode & 0777); 1050*64478Shibler shp->shm_ctime = time.tv_sec; 1051*64478Shibler } 1052*64478Shibler return (error); 105354857Shibler } 105454857Shibler return (shmctl(p, uap, retval)); 105554857Shibler } 105641486Smckusick #endif 105741486Smckusick 105841486Smckusick /* 105941486Smckusick * Fake semaphore routines, just don't return an error. 106041486Smckusick * Should be adequate for starbase to run. 106141486Smckusick */ 106254917Storek struct hpuxsemctl_args { 106354917Storek int semid; 106454917Storek u_int semnum; 106554917Storek int cmd; 106654917Storek int arg; 106754917Storek }; 106843452Shibler hpuxsemctl(p, uap, retval) 106943452Shibler struct proc *p; 107054917Storek struct hpuxsemctl_args *uap; 107143452Shibler int *retval; 107243452Shibler { 107341486Smckusick /* XXX: should do something here */ 107444421Skarels return (0); 107541486Smckusick } 107641486Smckusick 107754917Storek struct hpuxsemget_args { 107854917Storek key_t key; 107954917Storek int nsems; 108054917Storek int semflg; 108154917Storek }; 108243452Shibler hpuxsemget(p, uap, retval) 108343452Shibler struct proc *p; 108454917Storek struct hpuxsemget_args *uap; 108543452Shibler int *retval; 108643452Shibler { 108741486Smckusick /* XXX: should do something here */ 108844421Skarels return (0); 108941486Smckusick } 109041486Smckusick 109154917Storek struct hpuxsemop_args { 109254917Storek int semid; 109354917Storek struct sembuf *sops; 109454917Storek u_int nsops; 109554917Storek }; 109643452Shibler hpuxsemop(p, uap, retval) 109743452Shibler struct proc *p; 109854917Storek struct hpuxsemop_args *uap; 109943452Shibler int *retval; 110043452Shibler { 110141486Smckusick /* XXX: should do something here */ 110244421Skarels return (0); 110341486Smckusick } 110441486Smckusick 110557307Shibler /* 110657307Shibler * HP-UX mmap() emulation (mainly for shared library support). 110757307Shibler */ 110857307Shibler struct hpuxmmap_args { 110957307Shibler caddr_t addr; 111057307Shibler int len; 111157307Shibler int prot; 111257307Shibler int flags; 111357307Shibler int fd; 111457307Shibler long pos; 111557307Shibler }; 111657307Shibler hpuxmmap(p, uap, retval) 111757307Shibler struct proc *p; 111857307Shibler struct hpuxmmap_args *uap; 111957307Shibler int *retval; 112057307Shibler { 112157307Shibler struct mmap_args { 112257307Shibler caddr_t addr; 112357307Shibler int len; 112457307Shibler int prot; 112557307Shibler int flags; 112657307Shibler int fd; 112757307Shibler long pad; 112857307Shibler off_t pos; 112957307Shibler } nargs; 113057307Shibler 113157307Shibler nargs.addr = uap->addr; 113257307Shibler nargs.len = uap->len; 113357307Shibler nargs.prot = uap->prot; 113457307Shibler nargs.flags = uap->flags & 113557307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 113657307Shibler if (uap->flags & HPUXMAP_FIXED) 113757307Shibler nargs.flags |= MAP_FIXED; 113857307Shibler if (uap->flags & HPUXMAP_ANON) 113957307Shibler nargs.flags |= MAP_ANON; 114057307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 114157307Shibler nargs.pos = uap->pos; 114263440Sbostic return (mmap(p, &nargs, retval)); 114357307Shibler } 114457307Shibler 114554857Shibler /* convert from BSD to HP-UX errno */ 114641486Smckusick bsdtohpuxerrno(err) 114741486Smckusick int err; 114841486Smckusick { 114941486Smckusick if (err < 0 || err >= NERR) 115041486Smckusick return(BERR); 115141486Smckusick return((int)bsdtohpuxerrnomap[err]); 115241486Smckusick } 115341486Smckusick 115455282Smckusick hpuxstat1(fname, hsb, follow, p) 115541486Smckusick char *fname; 115641486Smckusick struct hpuxstat *hsb; 115741486Smckusick int follow; 115855282Smckusick struct proc *p; 115941486Smckusick { 116048478Skarels int error; 116141486Smckusick struct stat sb; 116248478Skarels struct nameidata nd; 116341486Smckusick 116455282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 116552330Smckusick if (error = namei(&nd)) 116641486Smckusick return (error); 116755282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 116852330Smckusick vput(nd.ni_vp); 116941486Smckusick if (error == 0) 117041486Smckusick error = bsdtohpuxstat(&sb, hsb); 117141486Smckusick return (error); 117241486Smckusick } 117341486Smckusick 117441486Smckusick #include "grf.h" 117553922Shibler #if NGRF > 0 117653922Shibler #ifdef __STDC__ 117753922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 117853922Shibler #else 117953922Shibler extern int grfopen(); 118053922Shibler #endif 118153922Shibler #endif 118241486Smckusick 118353922Shibler #define NHIL 1 /* XXX */ 118453922Shibler #if NHIL > 0 118553922Shibler #ifdef __STDC__ 118653922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 118753922Shibler #else 118853922Shibler extern int hilopen(); 118953922Shibler #endif 119053922Shibler #endif 119153922Shibler 119256506Sbostic #include <sys/conf.h> 119353922Shibler 119441486Smckusick bsdtohpuxstat(sb, hsb) 119541486Smckusick struct stat *sb; 119641486Smckusick struct hpuxstat *hsb; 119741486Smckusick { 119841486Smckusick struct hpuxstat ds; 119941486Smckusick 120041486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 120153481Smckusick ds.hst_dev = (u_short)sb->st_dev; 120241486Smckusick ds.hst_ino = (u_long)sb->st_ino; 120341486Smckusick ds.hst_mode = sb->st_mode; 120441486Smckusick ds.hst_nlink = sb->st_nlink; 120541486Smckusick ds.hst_uid = (u_short)sb->st_uid; 120641486Smckusick ds.hst_gid = (u_short)sb->st_gid; 120757307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 120857307Shibler 120953922Shibler /* XXX: I don't want to talk about it... */ 121053922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 121141486Smckusick #if NGRF > 0 121253922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 121353922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 121441486Smckusick #endif 121553922Shibler #if NHIL > 0 121653922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 121753922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 121853922Shibler #endif 121953922Shibler ; 122057307Shibler } 122153481Smckusick if (sb->st_size < (quad_t)1 << 32) 122253481Smckusick ds.hst_size = (long)sb->st_size; 122353481Smckusick else 122453481Smckusick ds.hst_size = -2; 122541486Smckusick ds.hst_atime = sb->st_atime; 122641486Smckusick ds.hst_mtime = sb->st_mtime; 122741486Smckusick ds.hst_ctime = sb->st_ctime; 122841486Smckusick ds.hst_blksize = sb->st_blksize; 122941486Smckusick ds.hst_blocks = sb->st_blocks; 123041486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 123141486Smckusick } 123241486Smckusick 123341486Smckusick hpuxtobsdioctl(com) 123441486Smckusick int com; 123541486Smckusick { 123641486Smckusick switch (com) { 123741486Smckusick case HPUXTIOCSLTC: 123841486Smckusick com = TIOCSLTC; break; 123941486Smckusick case HPUXTIOCGLTC: 124041486Smckusick com = TIOCGLTC; break; 124141486Smckusick case HPUXTIOCSPGRP: 124241486Smckusick com = TIOCSPGRP; break; 124341486Smckusick case HPUXTIOCGPGRP: 124441486Smckusick com = TIOCGPGRP; break; 124541486Smckusick case HPUXTIOCLBIS: 124641486Smckusick com = TIOCLBIS; break; 124741486Smckusick case HPUXTIOCLBIC: 124841486Smckusick com = TIOCLBIC; break; 124941486Smckusick case HPUXTIOCLSET: 125041486Smckusick com = TIOCLSET; break; 125141486Smckusick case HPUXTIOCLGET: 125241486Smckusick com = TIOCLGET; break; 1253*64478Shibler case HPUXTIOCGWINSZ: 1254*64478Shibler com = TIOCGWINSZ; break; 1255*64478Shibler case HPUXTIOCSWINSZ: 1256*64478Shibler com = TIOCSWINSZ; break; 125741486Smckusick } 125841486Smckusick return(com); 125941486Smckusick } 126041486Smckusick 126141486Smckusick /* 126254857Shibler * HP-UX ioctl system call. The differences here are: 126341486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 126449329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 126541486Smckusick * the sgttyb struct is 2 bytes longer 126641486Smckusick */ 126754917Storek struct hpuxioctl_args { 126854917Storek int fdes; 126954917Storek int cmd; 127054917Storek caddr_t cmarg; 127154917Storek }; 127243452Shibler hpuxioctl(p, uap, retval) 127343452Shibler struct proc *p; 127454917Storek register struct hpuxioctl_args *uap; 127543452Shibler int *retval; 127643452Shibler { 127745923Smckusick register struct filedesc *fdp = p->p_fd; 127843452Shibler register struct file *fp; 127943452Shibler register int com, error; 128041486Smckusick register u_int size; 128141486Smckusick caddr_t memp = 0; 128241486Smckusick #define STK_PARAMS 128 128341486Smckusick char stkbuf[STK_PARAMS]; 128441486Smckusick caddr_t data = stkbuf; 128541486Smckusick 128641486Smckusick com = uap->cmd; 128741486Smckusick 128841486Smckusick /* XXX */ 128943452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 129045923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 129141486Smckusick 129248478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 129348478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 129444421Skarels return (EBADF); 129543452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 129644421Skarels return (EBADF); 129741486Smckusick 129841486Smckusick /* 129941486Smckusick * Interpret high order word to find 130041486Smckusick * amount of data to be copied to/from the 130141486Smckusick * user's address space. 130241486Smckusick */ 130341486Smckusick size = IOCPARM_LEN(com); 130443452Shibler if (size > IOCPARM_MAX) 130544421Skarels return (ENOTTY); 130641486Smckusick if (size > sizeof (stkbuf)) { 130743452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 130841486Smckusick data = memp; 130941486Smckusick } 131041486Smckusick if (com&IOC_IN) { 131141486Smckusick if (size) { 131243452Shibler error = copyin(uap->cmarg, data, (u_int)size); 131343452Shibler if (error) { 131441486Smckusick if (memp) 131541486Smckusick free(memp, M_IOCTLOPS); 131644421Skarels return (error); 131741486Smckusick } 131841486Smckusick } else 131941486Smckusick *(caddr_t *)data = uap->cmarg; 132041486Smckusick } else if ((com&IOC_OUT) && size) 132141486Smckusick /* 132243452Shibler * Zero the buffer so the user always 132343452Shibler * gets back something deterministic. 132441486Smckusick */ 132541486Smckusick bzero(data, size); 132641486Smckusick else if (com&IOC_VOID) 132741486Smckusick *(caddr_t *)data = uap->cmarg; 132841486Smckusick 132941486Smckusick switch (com) { 133041486Smckusick 133149329Shibler case HPUXFIOSNBIO: 133249329Shibler { 133349329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 133449329Shibler int tmp; 133549329Shibler 133649329Shibler if (*(int *)data) 133749329Shibler *ofp |= UF_FIONBIO_ON; 133849329Shibler else 133949329Shibler *ofp &= ~UF_FIONBIO_ON; 134049329Shibler /* 134163726Shibler * Only set/clear if O_NONBLOCK/FNDELAY not in effect 134249329Shibler */ 134363726Shibler if ((*ofp & (UF_NONBLOCK_ON|UF_FNDELAY_ON)) == 0) { 134463726Shibler tmp = *ofp & UF_FIONBIO_ON; 134549329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 134649329Shibler (caddr_t)&tmp, p); 134749329Shibler } 134849329Shibler break; 134949329Shibler } 135049329Shibler 135141486Smckusick case HPUXTIOCCONS: 135241486Smckusick *(int *)data = 1; 135348478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 135441486Smckusick break; 135541486Smckusick 135641486Smckusick /* BSD-style job control ioctls */ 135741486Smckusick case HPUXTIOCLBIS: 135841486Smckusick case HPUXTIOCLBIC: 135941486Smckusick case HPUXTIOCLSET: 136041486Smckusick *(int *)data &= HPUXLTOSTOP; 136141486Smckusick if (*(int *)data & HPUXLTOSTOP) 136241486Smckusick *(int *)data = LTOSTOP; 136341486Smckusick /* fall into */ 1364*64478Shibler 1365*64478Shibler /* simple mapping cases */ 136641486Smckusick case HPUXTIOCLGET: 136741486Smckusick case HPUXTIOCSLTC: 136841486Smckusick case HPUXTIOCGLTC: 136941486Smckusick case HPUXTIOCSPGRP: 137041486Smckusick case HPUXTIOCGPGRP: 1371*64478Shibler case HPUXTIOCGWINSZ: 1372*64478Shibler case HPUXTIOCSWINSZ: 137348478Skarels error = (*fp->f_ops->fo_ioctl) 137448478Skarels (fp, hpuxtobsdioctl(com), data, p); 137543452Shibler if (error == 0 && com == HPUXTIOCLGET) { 137641486Smckusick *(int *)data &= LTOSTOP; 137741486Smckusick if (*(int *)data & LTOSTOP) 137841486Smckusick *(int *)data = HPUXLTOSTOP; 137941486Smckusick } 138041486Smckusick break; 138141486Smckusick 138255832Shibler /* SYS 5 termio and POSIX termios */ 138341486Smckusick case HPUXTCGETA: 138441486Smckusick case HPUXTCSETA: 138541486Smckusick case HPUXTCSETAW: 138641486Smckusick case HPUXTCSETAF: 138755832Shibler case HPUXTCGETATTR: 138855832Shibler case HPUXTCSETATTR: 138955832Shibler case HPUXTCSETATTRD: 139055832Shibler case HPUXTCSETATTRF: 1391*64478Shibler error = hpuxtermio(uap->fdes, com, data, p); 139241486Smckusick break; 139341486Smckusick 139441486Smckusick default: 139548478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 139641486Smckusick break; 139741486Smckusick } 139841486Smckusick /* 139941486Smckusick * Copy any data to user, size was 140041486Smckusick * already set and checked above. 140141486Smckusick */ 140243452Shibler if (error == 0 && (com&IOC_OUT) && size) 140343452Shibler error = copyout(data, uap->cmarg, (u_int)size); 140441486Smckusick if (memp) 140541486Smckusick free(memp, M_IOCTLOPS); 140644421Skarels return (error); 140741486Smckusick } 140841486Smckusick 140941486Smckusick /* 141041486Smckusick * Man page lies, behaviour here is based on observed behaviour. 141141486Smckusick */ 141254917Storek struct hpuxgetcontext_args { 141354917Storek char *buf; 141454917Storek int len; 141554917Storek }; 141643452Shibler hpuxgetcontext(p, uap, retval) 141743452Shibler struct proc *p; 141854917Storek struct hpuxgetcontext_args *uap; 141943452Shibler int *retval; 142043452Shibler { 142141486Smckusick int error = 0; 142241486Smckusick register int len; 142341486Smckusick 142453922Shibler #if defined(HP380) 142553922Shibler if (machineid == HP_380) { 142655072Spendry len = min(uap->len, sizeof(hpux040context)); 142753922Shibler if (len) 142853922Shibler error = copyout(hpux040context, uap->buf, len); 142953922Shibler if (error == 0) 143053922Shibler *retval = sizeof(hpux040context); 143153922Shibler return (error); 143253922Shibler } 143353922Shibler #endif 143455072Spendry len = min(uap->len, sizeof(hpuxcontext)); 143541486Smckusick if (len) 143641486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 143743452Shibler if (error == 0) 143843452Shibler *retval = sizeof(hpuxcontext); 143944421Skarels return (error); 144041486Smckusick } 144141486Smckusick 144241486Smckusick /* 144341486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 144441486Smckusick * Note we do not check the real uid or "saved" uid. 144541486Smckusick */ 144654917Storek struct hpuxgetpgrp2_args { 144754917Storek int pid; 144854917Storek }; 144943452Shibler hpuxgetpgrp2(cp, uap, retval) 145043452Shibler struct proc *cp; 145154917Storek register struct hpuxgetpgrp2_args *uap; 145243452Shibler int *retval; 145341486Smckusick { 145441486Smckusick register struct proc *p; 145541486Smckusick 145641486Smckusick if (uap->pid == 0) 145743452Shibler uap->pid = cp->p_pid; 145841486Smckusick p = pfind(uap->pid); 145943452Shibler if (p == 0) 146044421Skarels return (ESRCH); 146148478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 146248478Skarels !inferior(p)) 146344421Skarels return (EPERM); 146443452Shibler *retval = p->p_pgid; 146544421Skarels return (0); 146641486Smckusick } 146741486Smckusick 146841486Smckusick /* 146941486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 147041486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 147141486Smckusick */ 147254917Storek struct hpuxsetpgrp2_args { 147354917Storek int pid; 147454917Storek int pgrp; 147554917Storek }; 147643452Shibler hpuxsetpgrp2(p, uap, retval) 147743452Shibler struct proc *p; 147854917Storek struct hpuxsetpgrp2_args *uap; 147943452Shibler int *retval; 148043452Shibler { 148141486Smckusick /* empirically determined */ 148243452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 148344421Skarels return (EINVAL); 148448478Skarels return (setpgid(p, uap, retval)); 148541486Smckusick } 148641486Smckusick 148741486Smckusick /* 148855165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 148945753Smckusick */ 149054917Storek struct hpuxsetresuid_args { 149154917Storek int ruid; 149254917Storek int euid; 149354917Storek int suid; 149454917Storek }; 149545753Smckusick hpuxsetresuid(p, uap, retval) 149655165Smckusick struct proc *p; 149754917Storek struct hpuxsetresuid_args *uap; 149845753Smckusick int *retval; 149945753Smckusick { 150055165Smckusick return (osetreuid(p, uap, retval)); 150145753Smckusick } 150245753Smckusick 150354917Storek struct hpuxsetresgid_args { 150454917Storek int rgid; 150554917Storek int egid; 150654917Storek int sgid; 150754917Storek }; 150845753Smckusick hpuxsetresgid(p, uap, retval) 150955165Smckusick struct proc *p; 151054917Storek struct hpuxsetresgid_args *uap; 151145753Smckusick int *retval; 151245753Smckusick { 151355165Smckusick return (osetregid(p, uap, retval)); 151445753Smckusick } 151545753Smckusick 151657307Shibler struct hpuxrlimit_args { 151757307Shibler u_int which; 151857307Shibler struct orlimit *rlp; 151957307Shibler }; 152057307Shibler hpuxgetrlimit(p, uap, retval) 152157307Shibler struct proc *p; 152257307Shibler struct hpuxrlimit_args *uap; 152357307Shibler int *retval; 152457307Shibler { 152557307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 152657307Shibler return (EINVAL); 152757307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 152857307Shibler uap->which = RLIMIT_NOFILE; 152960110Smckusick return (ogetrlimit(p, uap, retval)); 153057307Shibler } 153157307Shibler 153257307Shibler hpuxsetrlimit(p, uap, retval) 153357307Shibler struct proc *p; 153457307Shibler struct hpuxrlimit_args *uap; 153557307Shibler int *retval; 153657307Shibler { 153757307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 153857307Shibler return (EINVAL); 153957307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 154057307Shibler uap->which = RLIMIT_NOFILE; 154160110Smckusick return (osetrlimit(p, uap, retval)); 154257307Shibler } 154357307Shibler 154445753Smckusick /* 154545753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 154645753Smckusick */ 154754917Storek struct hpuxlockf_args { 154854917Storek int fd; 154954917Storek int func; 155054917Storek long size; 155154917Storek }; 155245753Smckusick hpuxlockf(p, uap, retval) 155345753Smckusick struct proc *p; 155454917Storek struct hpuxlockf_args *uap; 155545753Smckusick int *retval; 155645753Smckusick { 155745753Smckusick return (0); 155845753Smckusick } 155945753Smckusick 156054917Storek struct hpuxgetaccess_args { 156154917Storek char *path; 156254917Storek int uid; 156354917Storek int ngroups; 156454917Storek int *gidset; 156554917Storek void *label; 156654917Storek void *privs; 156754917Storek }; 156845753Smckusick hpuxgetaccess(p, uap, retval) 156945753Smckusick register struct proc *p; 157054917Storek register struct hpuxgetaccess_args *uap; 157145753Smckusick int *retval; 157245753Smckusick { 157345753Smckusick int lgroups[NGROUPS]; 157445753Smckusick int error = 0; 157545753Smckusick register struct ucred *cred; 157645753Smckusick register struct vnode *vp; 157752330Smckusick struct nameidata nd; 157845753Smckusick 157945753Smckusick /* 158045753Smckusick * Build an appropriate credential structure 158145753Smckusick */ 158248478Skarels cred = crdup(p->p_ucred); 158345753Smckusick switch (uap->uid) { 158445753Smckusick case 65502: /* UID_EUID */ 158545753Smckusick break; 158645753Smckusick case 65503: /* UID_RUID */ 158748478Skarels cred->cr_uid = p->p_cred->p_ruid; 158845753Smckusick break; 158945753Smckusick case 65504: /* UID_SUID */ 159045753Smckusick error = EINVAL; 159145753Smckusick break; 159245753Smckusick default: 159345753Smckusick if (uap->uid > 65504) 159445753Smckusick error = EINVAL; 159545753Smckusick cred->cr_uid = uap->uid; 159645753Smckusick break; 159745753Smckusick } 159845753Smckusick switch (uap->ngroups) { 159945753Smckusick case -1: /* NGROUPS_EGID */ 160045753Smckusick cred->cr_ngroups = 1; 160145753Smckusick break; 160245753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 160345753Smckusick break; 160445753Smckusick case -2: /* NGROUPS_RGID */ 160545753Smckusick cred->cr_ngroups = 1; 160648478Skarels cred->cr_gid = p->p_cred->p_rgid; 160745753Smckusick break; 160845753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 160948478Skarels cred->cr_gid = p->p_cred->p_rgid; 161045753Smckusick break; 161145753Smckusick case -3: /* NGROUPS_SGID */ 161245753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 161345753Smckusick error = EINVAL; 161445753Smckusick break; 161545753Smckusick case -4: /* NGROUPS_SUPP */ 161645753Smckusick if (cred->cr_ngroups > 1) 161745753Smckusick cred->cr_gid = cred->cr_groups[1]; 161845753Smckusick else 161945753Smckusick error = EINVAL; 162045753Smckusick break; 162145753Smckusick default: 162245753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 162345753Smckusick error = copyin((caddr_t)uap->gidset, 162445753Smckusick (caddr_t)&lgroups[0], 162545753Smckusick uap->ngroups * sizeof(lgroups[0])); 162645753Smckusick else 162745753Smckusick error = EINVAL; 162845753Smckusick if (error == 0) { 162945753Smckusick int gid; 163045753Smckusick 163145753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 163245753Smckusick cred->cr_groups[gid] = lgroups[gid]; 163345753Smckusick cred->cr_ngroups = uap->ngroups; 163445753Smckusick } 163545753Smckusick break; 163645753Smckusick } 163745753Smckusick /* 163845753Smckusick * Lookup file using caller's effective IDs. 163945753Smckusick */ 164045753Smckusick if (error == 0) { 164152330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 164252330Smckusick uap->path, p); 164352330Smckusick error = namei(&nd); 164445753Smckusick } 164545753Smckusick if (error) { 164645753Smckusick crfree(cred); 164745753Smckusick return (error); 164845753Smckusick } 164945753Smckusick /* 165045753Smckusick * Use the constructed credentials for access checks. 165145753Smckusick */ 165252330Smckusick vp = nd.ni_vp; 165345753Smckusick *retval = 0; 165448478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 165545753Smckusick *retval |= R_OK; 165648478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 165745753Smckusick *retval |= W_OK; 165845753Smckusick /* XXX we return X_OK for root on VREG even if not */ 165948478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 166045753Smckusick *retval |= X_OK; 166145753Smckusick vput(vp); 166245753Smckusick crfree(cred); 166345753Smckusick return (error); 166445753Smckusick } 166545753Smckusick 166649134Skarels extern char kstack[]; 166741486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 166841486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 166941486Smckusick 167041486Smckusick /* simplified FP structure */ 167141486Smckusick struct bsdfp { 167241486Smckusick int save[54]; 167341486Smckusick int reg[24]; 167441486Smckusick int ctrl[3]; 167541486Smckusick }; 167641486Smckusick 167757307Shibler /* 167857307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 167957307Shibler */ 168057307Shibler hpuxtobsduoff(off, isps, p) 168157307Shibler int *off, *isps; 168257307Shibler struct proc *p; 168341486Smckusick { 168457307Shibler register int *ar0 = p->p_md.md_regs; 168541486Smckusick struct hpuxfp *hp; 168641486Smckusick struct bsdfp *bp; 168741486Smckusick register u_int raddr; 168841486Smckusick 168957307Shibler *isps = 0; 169057307Shibler 169148478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 169241486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 169348478Skarels return(UOFF(U_ar0)); 169441486Smckusick 169541486Smckusick #ifdef FPCOPROC 169657307Shibler /* FP registers from PCB */ 169741486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 169841486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 169941486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 170041486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 170141486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 170241486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 170341486Smckusick #endif 170441486Smckusick 170541486Smckusick /* 170641486Smckusick * Everything else we recognize comes from the kernel stack, 170741486Smckusick * so we convert off to an absolute address (if not already) 170841486Smckusick * for simplicity. 170941486Smckusick */ 171041486Smckusick if (off < (int *)ctob(UPAGES)) 171149134Skarels off = (int *)((u_int)off + (u_int)kstack); 171241486Smckusick 171341486Smckusick /* 171457307Shibler * General registers. 171554857Shibler * We know that the HP-UX registers are in the same order as ours. 171641486Smckusick * The only difference is that their PS is 2 bytes instead of a 171741486Smckusick * padded 4 like ours throwing the alignment off. 171841486Smckusick */ 171948478Skarels if (off >= ar0 && off < &ar0[18]) { 172041486Smckusick /* 172141486Smckusick * PS: return low word and high word of PC as HP-UX would 172241486Smckusick * (e.g. &u.u_ar0[16.5]). 172357307Shibler * 172457307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 172557307Shibler * it and passing such an offset to procxmt will cause 172657307Shibler * it to fail anyway. Instead, we just set the offset 172757307Shibler * to PS and let hpuxptrace() shift up the value returned. 172841486Smckusick */ 172957307Shibler if (off == &ar0[PS]) { 173057307Shibler #if 0 173148478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 173257307Shibler #else 173357307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 173457307Shibler #endif 173557307Shibler *isps = 1; 173657307Shibler } 173741486Smckusick /* 173857307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 173957307Shibler * is only 16 bits. 174041486Smckusick */ 174148478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 174248478Skarels raddr = (u_int) &ar0[PC]; 174341486Smckusick /* 174441486Smckusick * D0-D7, A0-A7: easy 174541486Smckusick */ 174641486Smckusick else 174748478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 174849134Skarels return((int)(raddr - (u_int)kstack)); 174941486Smckusick } 175041486Smckusick 175141486Smckusick /* everything else */ 175241486Smckusick return(-1); 175341486Smckusick } 175441486Smckusick 175541486Smckusick /* 175654857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 175741486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 175841486Smckusick * convert the entire user struct. 175941486Smckusick */ 176041486Smckusick hpuxdumpu(vp, cred) 176141486Smckusick struct vnode *vp; 176241486Smckusick struct ucred *cred; 176341486Smckusick { 176448478Skarels struct proc *p = curproc; 176541486Smckusick int error; 176641486Smckusick struct hpuxuser *faku; 176741486Smckusick struct bsdfp *bp; 176841486Smckusick short *foop; 176941486Smckusick 177041486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 177141486Smckusick /* 177241486Smckusick * Make sure there is no mistake about this 177341486Smckusick * being a real user structure. 177441486Smckusick */ 177541486Smckusick bzero((caddr_t)faku, ctob(1)); 177641486Smckusick /* 177741486Smckusick * Fill in the process sizes. 177841486Smckusick */ 177948478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 178048478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 178148478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 178241486Smckusick /* 178341486Smckusick * Fill in the exec header for CDB. 178441486Smckusick * This was saved back in exec(). As far as I can tell CDB 178541486Smckusick * only uses this information to verify that a particular 178641486Smckusick * core file goes with a particular binary. 178741486Smckusick */ 178857307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 178941486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 179041486Smckusick /* 179141486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 179254857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 179341486Smckusick * so we have to move it up. 179441486Smckusick */ 179552381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 179652381Smckusick foop = (short *) p->p_md.md_regs; 179741486Smckusick foop[32] = foop[33]; 179841486Smckusick foop[33] = foop[34]; 179941486Smckusick foop[34] = foop[35]; 180041486Smckusick #ifdef FPCOPROC 180141486Smckusick /* 180254857Shibler * Copy 68881 registers from our PCB format to HP-UX format 180341486Smckusick */ 180449134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 180541486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 180641486Smckusick sizeof(bp->save)); 180741486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 180841486Smckusick sizeof(bp->ctrl)); 180941486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 181041486Smckusick sizeof(bp->reg)); 181141486Smckusick #endif 181241486Smckusick /* 181341486Smckusick * Slay the dragon 181441486Smckusick */ 181541486Smckusick faku->hpuxu_dragon = -1; 181641486Smckusick /* 181741486Smckusick * Dump this artfully constructed page in place of the 181841486Smckusick * user struct page. 181941486Smckusick */ 182048478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 182148478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 182249134Skarels (int *)NULL, p); 182341486Smckusick /* 182441486Smckusick * Dump the remaining UPAGES-1 pages normally 182541486Smckusick */ 182641486Smckusick if (!error) 182749134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 182841486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 182949134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 183041486Smckusick free((caddr_t)faku, M_TEMP); 183141486Smckusick return(error); 183241486Smckusick } 183341486Smckusick 183441486Smckusick /* 183541486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 183641486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 183741486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 183841486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 183957307Shibler * 184057307Shibler * These are still needed as of HP-UX 7.05. 184141486Smckusick */ 184255832Shibler #ifdef COMPAT_OHPUX 184355832Shibler 184445753Smckusick #define HPUX_HZ 50 184545753Smckusick 184657307Shibler #include "sys/times.h" 184741486Smckusick 184841486Smckusick /* from old timeb.h */ 184941486Smckusick struct hpuxtimeb { 185041486Smckusick time_t time; 185141486Smckusick u_short millitm; 185241486Smckusick short timezone; 185341486Smckusick short dstflag; 185441486Smckusick }; 185541486Smckusick 185641486Smckusick /* ye ole stat structure */ 185741486Smckusick struct ohpuxstat { 185853481Smckusick u_short ohst_dev; 185941486Smckusick u_short ohst_ino; 186041486Smckusick u_short ohst_mode; 186141486Smckusick short ohst_nlink; 186241486Smckusick short ohst_uid; 186341486Smckusick short ohst_gid; 186453481Smckusick u_short ohst_rdev; 186541486Smckusick int ohst_size; 186641486Smckusick int ohst_atime; 186741486Smckusick int ohst_mtime; 186841486Smckusick int ohst_ctime; 186941486Smckusick }; 187041486Smckusick 187141486Smckusick /* 187241486Smckusick * SYS V style setpgrp() 187341486Smckusick */ 187443452Shibler ohpuxsetpgrp(p, uap, retval) 187543452Shibler register struct proc *p; 187643452Shibler int *uap, *retval; 187741486Smckusick { 187841486Smckusick if (p->p_pid != p->p_pgid) 187948478Skarels enterpgrp(p, p->p_pid, 0); 188043452Shibler *retval = p->p_pgid; 188145753Smckusick return (0); 188241486Smckusick } 188341486Smckusick 188454917Storek struct ohpuxtime_args { 188554917Storek long *tp; 188654917Storek }; 188743452Shibler ohpuxtime(p, uap, retval) 188843452Shibler struct proc *p; 188954917Storek register struct ohpuxtime_args *uap; 189054917Storek int *retval; 189141486Smckusick { 189245753Smckusick int error = 0; 189341486Smckusick 189441486Smckusick if (uap->tp) 189543452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 189643452Shibler sizeof (long)); 189754917Storek *(time_t *)retval = time.tv_sec; 189844421Skarels return (error); 189941486Smckusick } 190041486Smckusick 190154917Storek struct ohpuxstime_args { 190254917Storek int time; 190354917Storek }; 190443452Shibler ohpuxstime(p, uap, retval) 190543452Shibler struct proc *p; 190654917Storek register struct ohpuxstime_args *uap; 190743452Shibler int *retval; 190841486Smckusick { 190941486Smckusick struct timeval tv; 191043452Shibler int s, error; 191141486Smckusick 191241486Smckusick tv.tv_sec = uap->time; 191341486Smckusick tv.tv_usec = 0; 191448478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 191544421Skarels return (error); 191641486Smckusick 191741486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 191841486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 191941486Smckusick s = splhigh(); time = tv; splx(s); 192041486Smckusick resettodr(); 192144421Skarels return (0); 192241486Smckusick } 192341486Smckusick 192454917Storek struct ohpuxftime_args { 192554917Storek struct hpuxtimeb *tp; 192654917Storek }; 192743452Shibler ohpuxftime(p, uap, retval) 192843452Shibler struct proc *p; 192954917Storek register struct ohpuxftime_args *uap; 193043452Shibler int *retval; 193143452Shibler { 193241486Smckusick struct hpuxtimeb tb; 193341486Smckusick int s; 193441486Smckusick 193541486Smckusick s = splhigh(); 193641486Smckusick tb.time = time.tv_sec; 193741486Smckusick tb.millitm = time.tv_usec / 1000; 193841486Smckusick splx(s); 193941486Smckusick tb.timezone = tz.tz_minuteswest; 194041486Smckusick tb.dstflag = tz.tz_dsttime; 194144421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 194241486Smckusick } 194341486Smckusick 194454917Storek struct ohpuxalarm_args { 194554917Storek int deltat; 194654917Storek }; 194743452Shibler ohpuxalarm(p, uap, retval) 194843452Shibler register struct proc *p; 194954917Storek register struct ohpuxalarm_args *uap; 195043452Shibler int *retval; 195141486Smckusick { 195241486Smckusick int s = splhigh(); 195341486Smckusick 195441486Smckusick untimeout(realitexpire, (caddr_t)p); 195541486Smckusick timerclear(&p->p_realtimer.it_interval); 195643452Shibler *retval = 0; 195741486Smckusick if (timerisset(&p->p_realtimer.it_value) && 195841486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 195943452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 196041486Smckusick if (uap->deltat == 0) { 196141486Smckusick timerclear(&p->p_realtimer.it_value); 196241486Smckusick splx(s); 196344421Skarels return (0); 196441486Smckusick } 196541486Smckusick p->p_realtimer.it_value = time; 196641486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 196741486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 196841486Smckusick splx(s); 196944421Skarels return (0); 197041486Smckusick } 197141486Smckusick 197254917Storek struct ohpuxnice_args { 197354917Storek int niceness; 197454917Storek }; 197543452Shibler ohpuxnice(p, uap, retval) 197643452Shibler register struct proc *p; 197754917Storek register struct ohpuxnice_args *uap; 197843452Shibler int *retval; 197941486Smckusick { 198043452Shibler int error; 198141486Smckusick 198243452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 198343452Shibler if (error == 0) 198443452Shibler *retval = p->p_nice - NZERO; 198544421Skarels return (error); 198641486Smckusick } 198741486Smckusick 198854917Storek struct ohpuxtimes_args { 198954917Storek struct tms *tmsb; 199054917Storek }; 199143452Shibler ohpuxtimes(p, uap, retval) 199243452Shibler struct proc *p; 199354917Storek register struct ohpuxtimes_args *uap; 199454917Storek int *retval; 199541486Smckusick { 199654771Storek struct timeval ru, rs; 199741486Smckusick struct tms atms; 199843452Shibler int error; 199941486Smckusick 200054771Storek calcru(p, &ru, &rs, NULL); 200154771Storek atms.tms_utime = hpuxscale(&ru); 200254771Storek atms.tms_stime = hpuxscale(&rs); 200348478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 200448478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 200543452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 200643452Shibler if (error == 0) 200754917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 200844421Skarels return (error); 200941486Smckusick } 201041486Smckusick 201145753Smckusick /* 201245753Smckusick * Doesn't exactly do what the documentation says. 201345753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 201445753Smckusick * is what HP-UX returns. 201545753Smckusick */ 201645753Smckusick hpuxscale(tvp) 201741486Smckusick register struct timeval *tvp; 201841486Smckusick { 201945753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 202041486Smckusick } 202141486Smckusick 202241486Smckusick /* 202341486Smckusick * Set IUPD and IACC times on file. 202441486Smckusick * Can't set ICHG. 202541486Smckusick */ 202654917Storek struct ohpuxutime_args { 202754917Storek char *fname; 202854917Storek time_t *tptr; 202954917Storek }; 203043452Shibler ohpuxutime(p, uap, retval) 203143452Shibler struct proc *p; 203254917Storek register struct ohpuxutime_args *uap; 203343452Shibler int *retval; 203443452Shibler { 203548478Skarels register struct vnode *vp; 203641486Smckusick struct vattr vattr; 203741486Smckusick time_t tv[2]; 203843452Shibler int error; 203948478Skarels struct nameidata nd; 204041486Smckusick 204141486Smckusick if (uap->tptr) { 204243452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 204343452Shibler if (error) 204444421Skarels return (error); 204541486Smckusick } else 204641486Smckusick tv[0] = tv[1] = time.tv_sec; 204741486Smckusick vattr_null(&vattr); 204854107Smckusick vattr.va_atime.ts_sec = tv[0]; 204954107Smckusick vattr.va_atime.ts_nsec = 0; 205054107Smckusick vattr.va_mtime.ts_sec = tv[1]; 205154107Smckusick vattr.va_mtime.ts_nsec = 0; 205252330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 205352330Smckusick if (error = namei(&nd)) 205444421Skarels return (error); 205552330Smckusick vp = nd.ni_vp; 205642154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 205743452Shibler error = EROFS; 205841486Smckusick else 205952330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 206041486Smckusick vput(vp); 206144421Skarels return (error); 206241486Smckusick } 206341486Smckusick 206443452Shibler ohpuxpause(p, uap, retval) 206543452Shibler struct proc *p; 206643452Shibler int *uap, *retval; 206741486Smckusick { 206849134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 206942155Skarels /* always return EINTR rather than ERESTART... */ 207044421Skarels return (EINTR); 207141486Smckusick } 207241486Smckusick 207341486Smckusick /* 207441486Smckusick * The old fstat system call. 207541486Smckusick */ 207654917Storek struct ohpuxfstat_args { 207754917Storek int fd; 207854917Storek struct ohpuxstat *sb; 207954917Storek }; 208043452Shibler ohpuxfstat(p, uap, retval) 208143452Shibler struct proc *p; 208254917Storek register struct ohpuxfstat_args *uap; 208343452Shibler int *retval; 208443452Shibler { 208545923Smckusick register struct filedesc *fdp = p->p_fd; 208641486Smckusick struct file *fp; 208741486Smckusick 208848478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 208948478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 209044421Skarels return (EBADF); 209143452Shibler if (fp->f_type != DTYPE_VNODE) 209244421Skarels return (EINVAL); 209355282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 209441486Smckusick } 209541486Smckusick 209641486Smckusick /* 209741486Smckusick * Old stat system call. This version follows links. 209841486Smckusick */ 209954917Storek struct ohpuxstat_args { 210054917Storek char *fname; 210154917Storek struct ohpuxstat *sb; 210254917Storek }; 210343452Shibler ohpuxstat(p, uap, retval) 210443452Shibler struct proc *p; 210554917Storek register struct ohpuxstat_args *uap; 210643452Shibler int *retval; 210743452Shibler { 210843452Shibler int error; 210948478Skarels struct nameidata nd; 211041486Smckusick 211152330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 211252330Smckusick if (error = namei(&nd)) 211344421Skarels return (error); 211455282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 211552330Smckusick vput(nd.ni_vp); 211644421Skarels return (error); 211741486Smckusick } 211841486Smckusick 211941486Smckusick int 212055282Smckusick ohpuxstat1(vp, ub, p) 212157307Shibler struct vnode *vp; 212241486Smckusick struct ohpuxstat *ub; 212355282Smckusick struct proc *p; 212441486Smckusick { 212557307Shibler struct ohpuxstat ohsb; 212657307Shibler struct stat sb; 212757307Shibler int error; 212841486Smckusick 212957307Shibler error = vn_stat(vp, &sb, p); 213041486Smckusick if (error) 213157307Shibler return (error); 213257307Shibler 213357307Shibler ohsb.ohst_dev = sb.st_dev; 213457307Shibler ohsb.ohst_ino = sb.st_ino; 213557307Shibler ohsb.ohst_mode = sb.st_mode; 213657307Shibler ohsb.ohst_nlink = sb.st_nlink; 213757307Shibler ohsb.ohst_uid = sb.st_uid; 213857307Shibler ohsb.ohst_gid = sb.st_gid; 213957307Shibler ohsb.ohst_rdev = sb.st_rdev; 214057307Shibler if (sb.st_size < (quad_t)1 << 32) 214157307Shibler ohsb.ohst_size = sb.st_size; 214257307Shibler else 214357307Shibler ohsb.ohst_size = -2; 214457307Shibler ohsb.ohst_atime = sb.st_atime; 214557307Shibler ohsb.ohst_mtime = sb.st_mtime; 214657307Shibler ohsb.ohst_ctime = sb.st_ctime; 214757307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 214841486Smckusick } 214941486Smckusick #endif 215055832Shibler #endif 2151