hpux_compat.c
来自「早期freebsd实现」· C语言 代码 · 共 2,252 行 · 第 1/4 页
C
2,252 行
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: hpux_compat.c 1.64 93/08/05$ * * @(#)hpux_compat.c 8.4 (Berkeley) 2/13/94 *//* * Various HP-UX compatibility routines */#ifdef HPUXCOMPAT#ifndef COMPAT_43#define COMPAT_43#endif#include <sys/param.h>#include <sys/systm.h>#include <sys/signalvar.h>#include <sys/kernel.h>#include <sys/filedesc.h>#include <sys/proc.h>#include <sys/buf.h>#include <sys/wait.h>#include <sys/file.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/ioctl.h>#include <sys/ptrace.h>#include <sys/stat.h>#include <sys/syslog.h>#include <sys/malloc.h>#include <sys/mount.h>#include <sys/ipc.h>#include <sys/user.h>#include <sys/mman.h>#include <machine/cpu.h>#include <machine/reg.h>#include <machine/psl.h>#include <machine/vmparam.h>#include <hp/hpux/hpux.h>#include <hp/hpux/hpux_termio.h>#ifdef DEBUGint unimpresponse = 0;#endif/* SYS5 style UTSNAME info */struct hpuxutsname protoutsname = { "4.4bsd", "", "0.5", "B", "9000/3?0", ""};/* 6.0 and later style context */#if defined(HP380)char hpux040context[] = "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default";#endif#ifdef FPCOPROCchar hpuxcontext[] = "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default";#elsechar hpuxcontext[] = "standalone HP-MC68020 HP-MC68010 localroot default";#endif/* YP domainname */char domainname[MAXHOSTNAMELEN] = "unknown";int domainnamelen = 7;#define NERR 83#define BERR 1000/* indexed by BSD errno */short bsdtohpuxerrnomap[NERR] = {/*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,/*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19,/*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,/*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217,/*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,/*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,/*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR,/*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46, 251,BERR,/*80*/ BERR,BERR, 11};notimp(p, uap, retval, code, nargs) struct proc *p; int *uap, *retval; int code, nargs;{ int error = 0;#ifdef DEBUG register int *argp = uap; extern char *hpuxsyscallnames[]; printf("HP-UX %s(", hpuxsyscallnames[code]); if (nargs) while (nargs--) printf("%x%c", *argp++, nargs? ',' : ')'); else printf(")"); printf("\n"); switch (unimpresponse) { case 0: error = nosys(p, uap, retval); break; case 1: error = EINVAL; break; }#else error = nosys(p, uap, retval);#endif uprintf("HP-UX system call %d not implemented\n", code); return (error);}/* * HP-UX fork and vfork need to map the EAGAIN return value appropriately. */hpuxfork(p, uap, retval) struct proc *p; struct hpuxwait3_args *uap; int *retval;{ int error; error = fork(p, uap, retval); if (error == EAGAIN) error = OEAGAIN; return (error);}hpuxvfork(p, uap, retval) struct proc *p; struct hpuxwait3_args *uap; int *retval;{ int error; error = vfork(p, uap, retval); if (error == EAGAIN) error = OEAGAIN; return (error);}struct hpuxexecv_args { char *fname; char **argp; char **envp;};hpuxexecv(p, uap, retval) struct proc *p; struct hpuxexecv_args *uap; int *retval;{ extern int execve(); uap->envp = NULL; return (execve(p, uap, retval));}/* * HP-UX versions of wait and wait3 actually pass the parameters * (status pointer, options, rusage) into the kernel rather than * handling it in the C library stub. We also need to map any * termination signal from BSD to HP-UX. */struct hpuxwait3_args { int *status; int options; int rusage;};hpuxwait3(p, uap, retval) struct proc *p; struct hpuxwait3_args *uap; int *retval;{ /* rusage pointer must be zero */ if (uap->rusage) return (EINVAL); p->p_md.md_regs[PS] = PSL_ALLCC; p->p_md.md_regs[R0] = uap->options; p->p_md.md_regs[R1] = uap->rusage; return (hpuxwait(p, uap, retval));}struct hpuxwait_args { int *status;};hpuxwait(p, uap, retval) struct proc *p; struct hpuxwait_args *uap; int *retval;{ int sig, *statp, error; statp = uap->status; /* owait clobbers first arg */ error = owait(p, uap, retval); /* * HP-UX wait always returns EINTR when interrupted by a signal * (well, unless its emulating a BSD process, but we don't bother...) */ if (error == ERESTART) error = EINTR; if (error) return (error); sig = retval[1] & 0xFF; if (sig == WSTOPPED) { sig = (retval[1] >> 8) & 0xFF; retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; } else if (sig) retval[1] = (retval[1] & 0xFF00) | bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); if (statp) if (suword((caddr_t)statp, retval[1])) error = EFAULT; return (error);}struct hpuxwaitpid_args { int pid; int *status; int options; struct rusage *rusage; /* wait4 arg */};hpuxwaitpid(p, uap, retval) struct proc *p; struct hpuxwaitpid_args *uap; int *retval;{ int rv, sig, xstat, error; uap->rusage = 0; error = wait4(p, uap, retval); /* * HP-UX wait always returns EINTR when interrupted by a signal * (well, unless its emulating a BSD process, but we don't bother...) */ if (error == ERESTART) error = EINTR; if (error) return (error); if (uap->status) { /* * Wait4 already wrote the status out to user space, * pull it back, change the signal portion, and write * it back out. */ rv = fuword((caddr_t)uap->status); if (WIFSTOPPED(rv)) { sig = WSTOPSIG(rv); rv = W_STOPCODE(bsdtohpuxsig(sig)); } else if (WIFSIGNALED(rv)) { sig = WTERMSIG(rv); xstat = WEXITSTATUS(rv); rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | WCOREDUMP(rv); } (void)suword((caddr_t)uap->status, rv); } return (error);}/* * Old creat system call. */struct hpuxcreat_args { char *fname; int fmode;};hpuxcreat(p, uap, retval) struct proc *p; register struct hpuxcreat_args *uap; int *retval;{ struct nargs { char *fname; int mode; int crtmode; } openuap; openuap.fname = uap->fname; openuap.crtmode = uap->fmode; openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; return (open(p, &openuap, retval));}/* * XXX extensions to the fd_ofileflags flags. * Hate to put this there, but they do need to be per-file. */#define UF_NONBLOCK_ON 0x10#define UF_FNDELAY_ON 0x20#define UF_FIONBIO_ON 0x40/* * Must remap some bits in the mode mask. * O_CREAT, O_TRUNC, and O_EXCL must be remapped, * O_NONBLOCK is remapped and remembered, * O_FNDELAY is remembered, * O_SYNCIO is removed entirely. */struct hpuxopen_args { char *fname; int mode; int crtmode;};hpuxopen(p, uap, retval) struct proc *p; register struct hpuxopen_args *uap; int *retval;{ int mode, error; mode = uap->mode; uap->mode &= ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); if (mode & HPUXFCREAT) { /* * simulate the pre-NFS behavior that opening a * file for READ+CREATE ignores the CREATE (unless * EXCL is set in which case we will return the * proper error). */ if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) uap->mode |= O_CREAT; } if (mode & HPUXFTRUNC) uap->mode |= O_TRUNC; if (mode & HPUXFEXCL) uap->mode |= O_EXCL; if (mode & HPUXNONBLOCK) uap->mode |= O_NDELAY; error = open(p, uap, retval); /* * Record non-blocking mode for fcntl, read, write, etc. */ if (error == 0 && (uap->mode & O_NDELAY)) p->p_fd->fd_ofileflags[*retval] |= (mode & HPUXNONBLOCK) ? UF_NONBLOCK_ON : UF_FNDELAY_ON; return (error);}struct hpuxfcntl_args { int fdes; int cmd; int arg;};hpuxfcntl(p, uap, retval) struct proc *p; register struct hpuxfcntl_args *uap; int *retval;{ int mode, error, flg = F_POSIX; struct file *fp; char *pop; struct hpuxflock hfl; struct flock fl; struct vnode *vp; if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || (fp = p->p_fd->fd_ofiles[uap->fdes]) == NULL) return (EBADF); pop = &p->p_fd->fd_ofileflags[uap->fdes]; switch (uap->cmd) { case F_SETFL: if (uap->arg & HPUXNONBLOCK) *pop |= UF_NONBLOCK_ON; else *pop &= ~UF_NONBLOCK_ON; if (uap->arg & HPUXNDELAY) *pop |= UF_FNDELAY_ON; else *pop &= ~UF_FNDELAY_ON; if (*pop & (UF_NONBLOCK_ON|UF_FNDELAY_ON|UF_FIONBIO_ON)) uap->arg |= FNONBLOCK; else uap->arg &= ~FNONBLOCK; uap->arg &= ~(HPUXNONBLOCK|HPUXFSYNCIO|HPUXFREMOTE); break; case F_GETFL: case F_DUPFD: case F_GETFD: case F_SETFD: break; case HPUXF_SETLKW: flg |= F_WAIT; /* Fall into F_SETLK */ case HPUXF_SETLK: if (fp->f_type != DTYPE_VNODE) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)uap->arg, (caddr_t)&hfl, sizeof (hfl)); if (error) return (error); fl.l_start = hfl.hl_start; fl.l_len = hfl.hl_len; fl.l_pid = hfl.hl_pid; fl.l_type = hfl.hl_type; fl.l_whence = hfl.hl_whence; if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; switch (fl.l_type) { case F_RDLCK: if ((fp->f_flag & FREAD) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_WRLCK: if ((fp->f_flag & FWRITE) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_UNLCK: return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, F_POSIX)); default: return (EINVAL); } case F_GETLK: if (fp->f_type != DTYPE_VNODE) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)uap->arg, (caddr_t)&hfl, sizeof (hfl)); if (error) return (error); fl.l_start = hfl.hl_start; fl.l_len = hfl.hl_len; fl.l_pid = hfl.hl_pid; fl.l_type = hfl.hl_type; fl.l_whence = hfl.hl_whence; if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) return (error); hfl.hl_start = fl.l_start; hfl.hl_len = fl.l_len; hfl.hl_pid = fl.l_pid; hfl.hl_type = fl.l_type; hfl.hl_whence = fl.l_whence; return (copyout((caddr_t)&hfl, (caddr_t)uap->arg, sizeof (hfl))); default: return (EINVAL); } error = fcntl(p, uap, retval); if (error == 0 && uap->cmd == F_GETFL) { mode = *retval; *retval &= ~(O_CREAT|O_TRUNC|O_EXCL); if (mode & FNONBLOCK) { if (*pop & UF_NONBLOCK_ON) *retval |= HPUXNONBLOCK; if ((*pop & UF_FNDELAY_ON) == 0) *retval &= ~HPUXNDELAY; } if (mode & O_CREAT) *retval |= HPUXFCREAT; if (mode & O_TRUNC) *retval |= HPUXFTRUNC; if (mode & O_EXCL) *retval |= HPUXFEXCL; } return (error);}/* * Read and write calls. Same as BSD except for non-blocking behavior. * There are three types of non-blocking reads/writes in HP-UX checked * in the following order: * * O_NONBLOCK: return -1 and errno == EAGAIN * O_NDELAY: return 0 * FIOSNBIO: return -1 and errno == EWOULDBLOCK */struct hpuxrw_args { int fd;};hpuxread(p, uap, retval) struct proc *p; struct hpuxrw_args *uap; int *retval;{ int error; error = read(p, uap, retval); if (error == EWOULDBLOCK) { char *fp = &p->p_fd->fd_ofileflags[uap->fd]; if (*fp & UF_NONBLOCK_ON) { *retval = -1; error = OEAGAIN; } else if (*fp & UF_FNDELAY_ON) { *retval = 0; error = 0; } } return (error);}hpuxwrite(p, uap, retval) struct proc *p; struct hpuxrw_args *uap; int *retval;{ int error; error = write(p, uap, retval); if (error == EWOULDBLOCK) { char *fp = &p->p_fd->fd_ofileflags[uap->fd]; if (*fp & UF_NONBLOCK_ON) { *retval = -1; error = OEAGAIN; } else if (*fp & UF_FNDELAY_ON) { *retval = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?