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 + -
显示快捷键?