Example #1
0
long
setsignal(int signo, int vforked)
{
	int action;
	sig_t sigact = SIG_DFL;
	struct sigaction act, oact;
	char *t, tsig;

	if ((t = trap[signo]) == NULL)
		action = S_DFL;
	else if (*t != '\0')
		action = S_CATCH;
	else
		action = S_IGN;
	if (rootshell && !vforked && action == S_DFL) {
		switch (signo) {
		case SIGINT:
			if (iflag || minusc || sflag == 0)
				action = S_CATCH;
			break;
		case SIGQUIT:
#ifdef DEBUG
			if (debug)
				break;
#endif
			/* FALLTHROUGH */
		case SIGTERM:
			if (iflag)
				action = S_IGN;
			break;
#if JOBS
		case SIGTSTP:
		case SIGTTOU:
			if (mflag)
				action = S_IGN;
			break;
#endif
		}
	}

	t = &sigmode[signo - 1];
	tsig = *t;
	if (tsig == 0) {
		/*
		 * current setting unknown
		 */
		if (!getsigaction(signo, &sigact)) {
			/*
			 * Pretend it worked; maybe we should give a warning
			 * here, but other shells don't. We don't alter
			 * sigmode, so that we retry every time.
			 */
			return 0;
		}
		if (sigact == SIG_IGN) {
			if (mflag && (signo == SIGTSTP ||
			     signo == SIGTTIN || signo == SIGTTOU)) {
				tsig = S_IGN;	/* don't hard ignore these */
			} else
				tsig = S_HARD_IGN;
		} else {
			tsig = S_RESET;	/* force to be set */
		}
	}
	if (tsig == S_HARD_IGN || tsig == action)
		return 0;
	switch (action) {
		case S_DFL:	sigact = SIG_DFL;	break;
		case S_CATCH:  	sigact = onsig;		break;
		case S_IGN:	sigact = SIG_IGN;	break;
	}
	if (!vforked)
		*t = action;
    act.sa_handler = sigact;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
#ifdef SA_INTERRUPT
    act.sa_flags |= SA_INTERRUPT;
#endif
    if(sigaction(signo, &act, &oact) < 0)
        return (long) SIG_ERR;
    return (long) oact.sa_handler;
}
Example #2
0
/*
 * Set the signal handler for the specified signal.  The routine figures
 * out what it should be set to.
 */
void
setsignal(int signo)
{
	int action;
	sig_t sigact = SIG_DFL;
	struct sigaction sa;
	char *t;

	if ((t = trap[signo]) == NULL)
		action = S_DFL;
	else if (*t != '\0')
		action = S_CATCH;
	else
		action = S_IGN;
	if (action == S_DFL) {
		switch (signo) {
		case SIGINT:
			action = S_CATCH;
			break;
		case SIGQUIT:
#ifdef DEBUG
			{
			extern int debug;

			if (debug)
				break;
			}
#endif
			action = S_CATCH;
			break;
		case SIGTERM:
			if (rootshell && iflag)
				action = S_IGN;
			break;
#if JOBS
		case SIGTSTP:
		case SIGTTOU:
			if (rootshell && mflag)
				action = S_IGN;
			break;
#endif
#ifndef NO_HISTORY
		case SIGWINCH:
			if (rootshell && iflag)
				action = S_CATCH;
			break;
#endif
		}
	}

	t = &sigmode[signo];
	if (*t == 0) {
		/*
		 * current setting unknown
		 */
		if (!getsigaction(signo, &sigact)) {
			/*
			 * Pretend it worked; maybe we should give a warning
			 * here, but other shells don't. We don't alter
			 * sigmode, so that we retry every time.
			 */
			return;
		}
		if (sigact == SIG_IGN) {
			if (mflag && (signo == SIGTSTP ||
			     signo == SIGTTIN || signo == SIGTTOU)) {
				*t = S_IGN;	/* don't hard ignore these */
			} else
				*t = S_HARD_IGN;
		} else {
			*t = S_RESET;	/* force to be set */
		}
	}
	if (*t == S_HARD_IGN || *t == action)
		return;
	switch (action) {
		case S_DFL:	sigact = SIG_DFL;	break;
		case S_CATCH:  	sigact = onsig;		break;
		case S_IGN:	sigact = SIG_IGN;	break;
	}
	*t = action;
	sa.sa_handler = sigact;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	sigaction(signo, &sa, NULL);
}
Example #3
0
void
setsignal(shinstance *psh, int signo, int vforked)
{
	int action;
	shsig_t sigact = SH_SIG_DFL;
	char *t, tsig;

	if ((t = psh->trap[signo]) == NULL)
		action = S_DFL;
	else if (*t != '\0')
		action = S_CATCH;
	else
		action = S_IGN;
	if (psh->rootshell && !vforked && action == S_DFL) {
		switch (signo) {
		case SIGINT:
			if (iflag(psh) || psh->minusc || sflag(psh) == 0)
				action = S_CATCH;
			break;
		case SIGQUIT:
#ifdef DEBUG
			if (debug(psh))
				break;
#endif
			/* FALLTHROUGH */
		case SIGTERM:
			if (iflag(psh))
				action = S_IGN;
			break;
#if JOBS
		case SIGTSTP:
		case SIGTTOU:
			if (mflag(psh))
				action = S_IGN;
			break;
#endif
		}
	}

	t = &psh->sigmode[signo - 1];
	tsig = *t;
	if (tsig == 0) {
		/*
		 * current setting unknown
		 */
		if (!getsigaction(psh, signo, &sigact)) {
			/*
			 * Pretend it worked; maybe we should give a warning
			 * here, but other shells don't. We don't alter
			 * sigmode, so that we retry every time.
			 */
			return;
		}
		if (sigact == SH_SIG_IGN) {
			if (mflag(psh) && (signo == SIGTSTP ||
			     signo == SIGTTIN || signo == SIGTTOU)) {
				tsig = S_IGN;	/* don't hard ignore these */
			} else
				tsig = S_HARD_IGN;
		} else {
			tsig = S_RESET;	/* force to be set */
		}
	}
	if (tsig == S_HARD_IGN || tsig == action)
		return;
	switch (action) {
		case S_DFL:	sigact = SH_SIG_DFL;	break;
		case S_CATCH:  	sigact = onsig;		break;
		case S_IGN:	sigact = SH_SIG_IGN;	break;
	}
	if (!vforked)
		*t = action;
	sh_siginterrupt(psh, signo, 1);
	sh_signal(psh, signo, sigact);
}
Example #4
0
sig_t
setsignal(int signo, int vforked)
{
	int action;
	sig_t sigact = SIG_DFL, sig;
	char *t, tsig;

	if ((t = trap[signo]) == NULL)
		action = S_DFL;
	else if (*t != '\0')
		action = S_CATCH;
	else
		action = S_IGN;
	if (rootshell && !vforked && action == S_DFL) {
		switch (signo) {
		case SIGINT:
			if (iflag || minusc || sflag == 0)
				action = S_CATCH;
			break;
		case SIGQUIT:
#ifdef DEBUG
			if (debug)
				break;
#endif
			/* FALLTHROUGH */
		case SIGTERM:
			if (iflag)
				action = S_IGN;
			break;
#if JOBS
		case SIGTSTP:
		case SIGTTOU:
			if (mflag)
				action = S_IGN;
			break;
#endif
		}
	}

	t = &sigmode[signo - 1];
	tsig = *t;
	if (tsig == 0) {
		/*
		 * current setting unknown
		 */
		if (!getsigaction(signo, &sigact)) {
			/*
			 * Pretend it worked; maybe we should give a warning
			 * here, but other shells don't. We don't alter
			 * sigmode, so that we retry every time.
			 */
			return 0;
		}
		if (sigact == SIG_IGN) {
			/*
			 * POSIX 3.14.13 states that non-interactive shells
			 * should ignore trap commands for signals that were
			 * ignored upon entry, and leaves the behavior
			 * unspecified for interactive shells. On interactive
			 * shells, or if job control is on, and we have a job
			 * control related signal, we allow the trap to work.
			 *
			 * This change allows us to be POSIX compliant, and
			 * at the same time override the default behavior if
			 * we need to by setting the interactive flag.
			 */
			if ((mflag && (signo == SIGTSTP ||
			     signo == SIGTTIN || signo == SIGTTOU)) || iflag) {
				tsig = S_IGN;
			} else
				tsig = S_HARD_IGN;
		} else {
			tsig = S_RESET;	/* force to be set */
		}
	}
	if (tsig == S_HARD_IGN || tsig == action)
		return 0;
	switch (action) {
		case S_DFL:	sigact = SIG_DFL;	break;
		case S_CATCH:  	sigact = onsig;		break;
		case S_IGN:	sigact = SIG_IGN;	break;
	}
	sig = signal(signo, sigact);
	if (sig != SIG_ERR) {
		sigset_t ss;
		if (!vforked)
			*t = action;
		if (action == S_CATCH)
			(void)siginterrupt(signo, 1);
		/*
		 * If our parent accidentally blocked signals for
		 * us make sure we unblock them
		 */
		(void)sigemptyset(&ss);
		(void)sigaddset(&ss, signo);
		(void)sigprocmask(SIG_UNBLOCK, &ss, NULL);
	}
	return sig;
}
Example #5
0
/*
 * Set the signal handler for the specified signal.  The routine figures
 * out what it should be set to.
 */
void
setsignal(int signo, int vforked)
{
	int action;
	sig_t sigact = SIG_DFL, sig;
	char *t, tsig;

	if ((t = trap[signo]) == NULL)
		action = S_DFL;
	else if (*t != '\0')
		action = S_CATCH;
	else
		action = S_IGN;

	VTRACE(DBG_TRAP, ("setsignal(%d%s) -> %d", signo,
	    vforked ? ", VF" : "", action));
	if (rootshell && !vforked && action == S_DFL) {
		switch (signo) {
		case SIGINT:
			if (iflag || minusc || sflag == 0)
				action = S_CATCH;
			break;
		case SIGQUIT:
#ifdef DEBUG
			if (debug)
				break;
#endif
			/* FALLTHROUGH */
		case SIGTERM:
			if (rootshell && iflag)
				action = S_IGN;
			break;
#if JOBS
		case SIGTSTP:
		case SIGTTOU:
			if (rootshell && mflag)
				action = S_IGN;
			break;
#endif
		}
	}

	/*
	 * Never let users futz with SIGCHLD
	 * instead we will give them pseudo SIGCHLD's
	 * when background jobs complete.
	 */
	if (signo == SIGCHLD)
		action = S_DFL;

	VTRACE(DBG_TRAP, (" -> %d", action));

	t = &sigmode[signo];
	tsig = *t;
	if (tsig == 0) {
		/*
		 * current setting unknown
		 */
		if (!getsigaction(signo, &sigact)) {
			/*
			 * Pretend it worked; maybe we should give a warning
			 * here, but other shells don't. We don't alter
			 * sigmode, so that we retry every time.
			 */
			VTRACE(DBG_TRAP, (" getsigaction (%d)\n", errno));
			return;
		}
		VTRACE(DBG_TRAP, (" [%s]%s%s", sigact==SIG_IGN ? "IGN" :
		    sigact==SIG_DFL ? "DFL" : "caught",
		    iflag ? "i" : "", mflag ? "m" : ""));

		if (sigact == SIG_IGN) {
			/*
			 * POSIX 3.14.13 states that non-interactive shells
			 * should ignore trap commands for signals that were
			 * ignored upon entry, and leaves the behavior
			 * unspecified for interactive shells. On interactive
			 * shells, or if job control is on, and we have a job
			 * control related signal, we allow the trap to work.
			 *
			 * This change allows us to be POSIX compliant, and
			 * at the same time override the default behavior if
			 * we need to by setting the interactive flag.
			 */
			if ((mflag && (signo == SIGTSTP ||
			     signo == SIGTTIN || signo == SIGTTOU)) || iflag) {
				tsig = S_IGN;
			} else
				tsig = S_HARD_IGN;
		} else {
			tsig = S_RESET;	/* force to be set */
		}
	}
	VTRACE(DBG_TRAP, (" tsig=%d\n", tsig));

	if (tsig == S_HARD_IGN || tsig == action)
		return;

	switch (action) {
		case S_DFL:	sigact = SIG_DFL;	break;
		case S_CATCH:  	sigact = onsig;		break;
		case S_IGN:	sigact = SIG_IGN;	break;
	}

	sig = signal(signo, sigact);

	if (sig != SIG_ERR) {
		sigset_t ss;

		if (!vforked)
			*t = action;

		if (action == S_CATCH)
			(void)siginterrupt(signo, 1);
		/*
		 * If our parent accidentally blocked signals for
		 * us make sure we unblock them
		 */
		(void)sigemptyset(&ss);
		(void)sigaddset(&ss, signo);
		(void)sigprocmask(SIG_UNBLOCK, &ss, NULL);
	}
	return;
}