⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kern_sig.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1989, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * *	@(#)kern_sig.c	8.7 (Berkeley) 4/18/94 */#define	SIGPROP		/* include signal properties table */#include <sys/param.h>#include <sys/signalvar.h>#include <sys/resourcevar.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/proc.h>#include <sys/systm.h>#include <sys/timeb.h>#include <sys/times.h>#include <sys/buf.h>#include <sys/acct.h>#include <sys/file.h>#include <sys/kernel.h>#include <sys/wait.h>#include <sys/ktrace.h>#include <sys/syslog.h>#include <sys/stat.h>#include <machine/cpu.h>#include <vm/vm.h>#include <sys/user.h>		/* for coredump *//* * Can process p, with pcred pc, send the signal signum to process q? */#define CANSIGNAL(p, pc, q, signum) \	((pc)->pc_ucred->cr_uid == 0 || \	    (pc)->p_ruid == (q)->p_cred->p_ruid || \	    (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \	    (pc)->p_ruid == (q)->p_ucred->cr_uid || \	    (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \	    ((signum) == SIGCONT && (q)->p_session == (p)->p_session))struct sigaction_args {	int	signum;	struct	sigaction *nsa;	struct	sigaction *osa;};/* ARGSUSED */sigaction(p, uap, retval)	struct proc *p;	register struct sigaction_args *uap;	int *retval;{	struct sigaction vec;	register struct sigaction *sa;	register struct sigacts *ps = p->p_sigacts;	register int signum;	int bit, error;	signum = uap->signum;	if (signum <= 0 || signum >= NSIG ||	    signum == SIGKILL || signum == SIGSTOP)		return (EINVAL);	sa = &vec;	if (uap->osa) {		sa->sa_handler = ps->ps_sigact[signum];		sa->sa_mask = ps->ps_catchmask[signum];		bit = sigmask(signum);		sa->sa_flags = 0;		if ((ps->ps_sigonstack & bit) != 0)			sa->sa_flags |= SA_ONSTACK;		if ((ps->ps_sigintr & bit) == 0)			sa->sa_flags |= SA_RESTART;		if (p->p_flag & P_NOCLDSTOP)			sa->sa_flags |= SA_NOCLDSTOP;		if (error = copyout((caddr_t)sa, (caddr_t)uap->osa,		    sizeof (vec)))			return (error);	}	if (uap->nsa) {		if (error = copyin((caddr_t)uap->nsa, (caddr_t)sa,		    sizeof (vec)))			return (error);		setsigvec(p, signum, sa);	}	return (0);}setsigvec(p, signum, sa)	register struct proc *p;	int signum;	register struct sigaction *sa;{	register struct sigacts *ps = p->p_sigacts;	register int bit;	bit = sigmask(signum);	/*	 * Change setting atomically.	 */	(void) splhigh();	ps->ps_sigact[signum] = sa->sa_handler;	ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask;	if ((sa->sa_flags & SA_RESTART) == 0)		ps->ps_sigintr |= bit;	else		ps->ps_sigintr &= ~bit;	if (sa->sa_flags & SA_ONSTACK)		ps->ps_sigonstack |= bit;	else		ps->ps_sigonstack &= ~bit;#ifdef COMPAT_SUNOS	if (sa->sa_flags & SA_USERTRAMP)		ps->ps_usertramp |= bit;	else		ps->ps_usertramp &= ~bit;#endif	if (signum == SIGCHLD) {		if (sa->sa_flags & SA_NOCLDSTOP)			p->p_flag |= P_NOCLDSTOP;		else			p->p_flag &= ~P_NOCLDSTOP;	}	/*	 * Set bit in p_sigignore for signals that are set to SIG_IGN,	 * and for signals set to SIG_DFL where the default is to ignore.	 * However, don't put SIGCONT in p_sigignore,	 * as we have to restart the process.	 */	if (sa->sa_handler == SIG_IGN ||	    (sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) {		p->p_siglist &= ~bit;		/* never to be seen again */		if (signum != SIGCONT)			p->p_sigignore |= bit;	/* easier in psignal */		p->p_sigcatch &= ~bit;	} else {		p->p_sigignore &= ~bit;		if (sa->sa_handler == SIG_DFL)			p->p_sigcatch &= ~bit;		else			p->p_sigcatch |= bit;	}	(void) spl0();}/* * Initialize signal state for process 0; * set to ignore signals that are ignored by default. */voidsiginit(p)	struct proc *p;{	register int i;	for (i = 0; i < NSIG; i++)		if (sigprop[i] & SA_IGNORE && i != SIGCONT)			p->p_sigignore |= sigmask(i);}/* * Reset signals for an exec of the specified process. */voidexecsigs(p)	register struct proc *p;{	register struct sigacts *ps = p->p_sigacts;	register int nc, mask;	/*	 * Reset caught signals.  Held signals remain held	 * through p_sigmask (unless they were caught,	 * and are now ignored by default).	 */	while (p->p_sigcatch) {		nc = ffs((long)p->p_sigcatch);		mask = sigmask(nc);		p->p_sigcatch &= ~mask;		if (sigprop[nc] & SA_IGNORE) {			if (nc != SIGCONT)				p->p_sigignore |= mask;			p->p_siglist &= ~mask;		}		ps->ps_sigact[nc] = SIG_DFL;	}	/*	 * Reset stack state to the user stack.	 * Clear set of signals caught on the signal stack.	 */	ps->ps_sigstk.ss_flags = SA_DISABLE;	ps->ps_sigstk.ss_size = 0;	ps->ps_sigstk.ss_base = 0;	ps->ps_flags = 0;}/* * Manipulate signal mask. * Note that we receive new mask, not pointer, * and return old mask as return value; * the library stub does the rest. */struct sigprocmask_args {	int	how;	sigset_t mask;};sigprocmask(p, uap, retval)	register struct proc *p;	struct sigprocmask_args *uap;	int *retval;{	int error = 0;	*retval = p->p_sigmask;	(void) splhigh();	switch (uap->how) {	case SIG_BLOCK:		p->p_sigmask |= uap->mask &~ sigcantmask;		break;	case SIG_UNBLOCK:		p->p_sigmask &= ~uap->mask;		break;	case SIG_SETMASK:		p->p_sigmask = uap->mask &~ sigcantmask;		break;		default:		error = EINVAL;		break;	}	(void) spl0();	return (error);}struct sigpending_args {	int	dummy;};/* ARGSUSED */sigpending(p, uap, retval)	struct proc *p;	struct sigpending_args *uap;	int *retval;{	*retval = p->p_siglist;	return (0);}#if defined(COMPAT_43) || defined(COMPAT_SUNOS)/* * Generalized interface signal handler, 4.3-compatible. */struct osigvec_args {	int	signum;	struct	sigvec *nsv;	struct	sigvec *osv;};/* ARGSUSED */osigvec(p, uap, retval)	struct proc *p;	register struct osigvec_args *uap;	int *retval;{	struct sigvec vec;	register struct sigacts *ps = p->p_sigacts;	register struct sigvec *sv;	register int signum;	int bit, error;	signum = uap->signum;	if (signum <= 0 || signum >= NSIG ||	    signum == SIGKILL || signum == SIGSTOP)		return (EINVAL);	sv = &vec;	if (uap->osv) {		*(sig_t *)&sv->sv_handler = ps->ps_sigact[signum];		sv->sv_mask = ps->ps_catchmask[signum];		bit = sigmask(signum);		sv->sv_flags = 0;		if ((ps->ps_sigonstack & bit) != 0)			sv->sv_flags |= SV_ONSTACK;		if ((ps->ps_sigintr & bit) != 0)			sv->sv_flags |= SV_INTERRUPT;#ifndef COMPAT_SUNOS		if (p->p_flag & P_NOCLDSTOP)			sv->sv_flags |= SA_NOCLDSTOP;#endif		if (error = copyout((caddr_t)sv, (caddr_t)uap->osv,		    sizeof (vec)))			return (error);	}	if (uap->nsv) {		if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv,		    sizeof (vec)))			return (error);#ifdef COMPAT_SUNOS		/*		 * SunOS uses this bit (4, aka SA_DISABLE) as SV_RESETHAND,		 * `reset to SIG_DFL on delivery'. We have no such option		 * now or ever!		 */		if (sv->sv_flags & SA_DISABLE)			return (EINVAL);		sv->sv_flags |= SA_USERTRAMP;#endif		sv->sv_flags ^= SA_RESTART;	/* opposite of SV_INTERRUPT */		setsigvec(p, signum, (struct sigaction *)sv);	}	return (0);}struct osigblock_args {	int	mask;};osigblock(p, uap, retval)	register struct proc *p;	struct osigblock_args *uap;	int *retval;{	(void) splhigh();	*retval = p->p_sigmask;	p->p_sigmask |= uap->mask &~ sigcantmask;	(void) spl0();	return (0);}struct osigsetmask_args {	int	mask;};osigsetmask(p, uap, retval)	struct proc *p;	struct osigsetmask_args *uap;	int *retval;{	(void) splhigh();	*retval = p->p_sigmask;	p->p_sigmask = uap->mask &~ sigcantmask;	(void) spl0();	return (0);}#endif /* COMPAT_43 || COMPAT_SUNOS *//* * Suspend process until signal, providing mask to be set * in the meantime.  Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. */struct sigsuspend_args {	sigset_t mask;};/* ARGSUSED */sigsuspend(p, uap, retval)	register struct proc *p;	struct sigsuspend_args *uap;	int *retval;{	register struct sigacts *ps = p->p_sigacts;	/*	 * When returning from sigpause, we want	 * the old mask to be restored after the	 * signal handler has finished.  Thus, we	 * save it here and mark the sigacts structure	 * to indicate this.	 */	ps->ps_oldmask = p->p_sigmask;	ps->ps_flags |= SAS_OLDMASK;	p->p_sigmask = uap->mask &~ sigcantmask;	while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0)		/* void */;	/* always return EINTR rather than ERESTART... */	return (EINTR);}#if defined(COMPAT_43) || defined(COMPAT_SUNOS)struct osigstack_args {	struct	sigstack *nss;	struct	sigstack *oss;};/* ARGSUSED */osigstack(p, uap, retval)	struct proc *p;	register struct osigstack_args *uap;	int *retval;{	struct sigstack ss;	struct sigacts *psp;	int error = 0;	psp = p->p_sigacts;	ss.ss_sp = psp->ps_sigstk.ss_base;	ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;	if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss,	    sizeof (struct sigstack))))		return (error);	if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss,	    sizeof (ss))) == 0) {		psp->ps_sigstk.ss_base = ss.ss_sp;		psp->ps_sigstk.ss_size = 0;		psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK;		psp->ps_flags |= SAS_ALTSTACK;	}	return (error);}#endif /* COMPAT_43 || COMPAT_SUNOS */struct sigaltstack_args {	struct	sigaltstack *nss;	struct	sigaltstack *oss;};/* ARGSUSED */sigaltstack(p, uap, retval)	struct proc *p;	register struct sigaltstack_args *uap;	int *retval;{	struct sigacts *psp;	struct sigaltstack ss;	int error;	psp = p->p_sigacts;	if ((psp->ps_flags & SAS_ALTSTACK) == 0)		psp->ps_sigstk.ss_flags |= SA_DISABLE;	if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk,	    (caddr_t)uap->oss, sizeof (struct sigaltstack))))		return (error);	if (uap->nss == 0)		return (0);	if (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)))		return (error);	if (ss.ss_flags & SA_DISABLE) {		if (psp->ps_sigstk.ss_flags & SA_ONSTACK)			return (EINVAL);		psp->ps_flags &= ~SAS_ALTSTACK;		psp->ps_sigstk.ss_flags = ss.ss_flags;		return (0);	}	if (ss.ss_size < MINSIGSTKSZ)		return (ENOMEM);	psp->ps_flags |= SAS_ALTSTACK;	psp->ps_sigstk= ss;	return (0);}struct kill_args {	int	pid;	int	signum;};/* ARGSUSED */kill(cp, uap, retval)	register struct proc *cp;	register struct kill_args *uap;	int *retval;{	register struct proc *p;	register struct pcred *pc = cp->p_cred;	if ((u_int)uap->signum >= NSIG)		return (EINVAL);	if (uap->pid > 0) {		/* kill single process */		if ((p = pfind(uap->pid)) == NULL)			return (ESRCH);		if (!CANSIGNAL(cp, pc, p, uap->signum))			return (EPERM);		if (uap->signum)			psignal(p, uap->signum);		return (0);	}	switch (uap->pid) {	case -1:		/* broadcast signal */		return (killpg1(cp, uap->signum, 0, 1));	case 0:			/* signal own process group */		return (killpg1(cp, uap->signum, 0, 0));	default:		/* negative explicit process group */		return (killpg1(cp, uap->signum, -uap->pid, 0));	}	/* NOTREACHED */}#if defined(COMPAT_43) || defined(COMPAT_SUNOS)struct okillpg_args {	int	pgid;	int	signum;};/* ARGSUSED */okillpg(p, uap, retval)	struct proc *p;	register struct okillpg_args *uap;	int *retval;{	if ((u_int)uap->signum >= NSIG)		return (EINVAL);	return (killpg1(p, uap->signum, uap->pgid, 0));}#endif /* COMPAT_43 || COMPAT_SUNOS *//* * Common code for kill process group/broadcast kill. * cp is calling process. */killpg1(cp, signum, pgid, all)	register struct proc *cp;	int signum, pgid, all;{	register struct proc *p;	register struct pcred *pc = cp->p_cred;	struct pgrp *pgrp;	int nfound = 0;		if (all)			/* 		 * broadcast 		 */		for (p = (struct proc *)allproc; p != NULL; p = p->p_next) {			if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || 			    p == cp || !CANSIGNAL(cp, pc, p, signum))				continue;			nfound++;			if (signum)				psignal(p, signum);		}	else {		if (pgid == 0)					/* 			 * zero pgid means send to my process group.			 */			pgrp = cp->p_pgrp;		else {			pgrp = pgfind(pgid);			if (pgrp == NULL)				return (ESRCH);		}		for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) {			if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||			    p->p_stat == SZOMB ||			    !CANSIGNAL(cp, pc, p, signum))				continue;			nfound++;			if (signum)				psignal(p, signum);		}	}	return (nfound ? 0 : ESRCH);}/* * Send a signal to a process group. */voidgsignal(pgid, signum)	int pgid, signum;{	struct pgrp *pgrp;	if (pgid && (pgrp = pgfind(pgid)))		pgsignal(pgrp, signum, 0);}/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -