/******************************************************************************
 * This file is part of a software distribution, which is furnished under the *
 * terms of a license.  Use of this software  by any means is subject to this *
 * license  and  signifies  the  acceptance of  the  licensing  terms  stated *
 * therein. Please see  the file LICENSE in the  top-level directory  of this *
 * software  distribution  for detailed copyright  disclaimers  and licensing *
 * terms.                                                                     *
 ******************************************************************************
 * Copryight (c) by Andreas S. Wetzel - All rights reserved.                  *
 ******************************************************************************/

/* $Id: sigctl.c,v 1.2 2001/03/19 14:54:02 mickey Exp $ */

#include <vchat.h>
#include <proto_common.h>

#include <fcntl.h>
#include <signal.h>

#if HAVE_STROPTS_H && HAVE_SYS_CONF_H
  #include <stropts.h>
  #include <sys/conf.h>
#endif

/*** Globals ***/

u_char	is_handler = 0;		/* 0 = user mode ; 1 = sighandler */

/*** Externals ***/

extern VCONN sconn;

extern void resize(void);

/*** Code ***/

void v_io_init(void)
{
#if HAVE_SIGACTION
	struct sigaction sa;

	sa.sa_handler = (void *)rcv_sv_msg;

	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGALRM);
	sigaddset(&sa.sa_mask, SIGWINCH);

  #if defined(SA_RESTART)
	sa.sa_flags = SA_RESTART;
  #else
	sa.sa_flags = 0;
  #endif
	sigaction(SIGIO, &sa, NULL);

#else /*** SIGVEC ***/

	struct sigvec sv;

	sv.sv_handler = (void *)rcv_sv_msg;

	sv.sv_mask = sigmask(SIGALRM);
	sv.sv_mask |= sigmask(SIGWINCH);

	sv.sv_flags = 0;

	sigvec(SIGIO, &sv, NULL);
#endif
	async_io(1);
}

void v_timer_init(void)
{
	struct itimerval it;
#if HAVE_SIGACTION

	struct sigaction sa;

	sa.sa_handler = (void *)heartbeat;

	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGIO);
	sigaddset(&sa.sa_mask, SIGWINCH);

  #if defined(SA_RESTART)
	sa.sa_flags = SA_RESTART;
  #else
	sa.sa_flags = 0;
  #endif
	sigaction(SIGALRM, &sa, NULL);

#else /*** SIGVEC ***/

	struct sigvec sv;

	sv.sv_handler = (void *)heartbeat;

	sv.sv_mask = sigmask(SIGIO);
	sv.sv_mask |= sigmask(SIGWINCH);

	sv.sv_flags = 0;

	sigvec(SIGALRM, &sv, NULL);
#endif
	it.it_interval.tv_sec = it.it_value.tv_sec = 1;
	it.it_interval.tv_usec = it.it_value.tv_usec = 0;

	setitimer(ITIMER_REAL, &it, NULL);
}

void v_winch_init(void)
{
#if HAVE_SIGACTION

	struct sigaction sa;

	sa.sa_handler = (void *)resize;

	sigemptyset(&sa.sa_mask);
	sigaddset(&sa.sa_mask, SIGIO);
	sigaddset(&sa.sa_mask, SIGALRM);

  #if defined(SA_RESTART)
	sa.sa_flags = SA_RESTART;
  #else
	sa.sa_flags = 0;
  #endif
	sigaction(SIGWINCH, &sa, NULL);

#else /*** SIGVEC ***/

	struct sigvec sv;

	sv.sv_handler = (void *)resize;

	sv.sv_mask = sigmask(SIGIO);
	sv.sv_mask |= sigmask(SIGALRM);

	sv.sv_flags = 0;

	sigvec(SIGWINCH, &sv, NULL);
#endif
}

void v_io_end(void)
{
#if HAVE_SIGACTION
	struct sigaction sa;

	async_io(0);

	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sigaction(SIGIO, &sa, NULL);
#else
	struct sigvec sv;

	async_io(0);

	sv.sv_handler = SIG_IGN;
	sigemptyset(&sv.sv_mask);
	sv.sv_flags = 0;

	sigvec(SIGIO, &sv, NULL);
#endif
}

void v_timer_end(void)
{
	struct itimerval it = {{0,0},{0,0}};
#if HAVE_SIGACTION
	struct sigaction sa;

	setitimer(ITIMER_REAL, &it, NULL);

	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sigaction(SIGALRM, &sa, NULL);
#else
	struct sigvec sv;

	setitimer(ITIMER_REAL, &it, NULL);

	sv.sv_handler = SIG_IGN;
	sigemptyset(&sv.sv_mask);
	sv.sv_flags = 0;

	sigvec(SIGALRM, &sv, NULL);
#endif
}

void v_winch_end(void)
{
#if HAVE_SIGACTION
	struct sigaction sa;

	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sigaction(SIGWINCH, &sa, NULL);
#else
	struct sigvec sv;

	sv.sv_handler = SIG_IGN;
	sigemptyset(&sv.sv_mask);
	sv.sv_flags = 0;

	sigvec(SIGWINCH, &sv, NULL);
#endif
}

void vlock(u_char mode, u_char items)
{
	sigset_t smask;

	static u_char locks_vio = 0;
	static u_char locks_vtimer = 0;
	static u_char locks_vwinch = 0;

	u_char has_changed = 0;

	/*
	 * We do nothing if we are called
	 * from within a signal handler.
	 */

	if(is_handler)
		return;

	if(mode == LOCK)
	{
		/*
		 * Lock the given set of signals
		 * Signals are locked only if the number
		 * of locks for this signal equals zero
		 * and the signal is not already locked
		 * by another instance.
		 */

		sigemptyset(&smask);

		if(items & V_IO)
		{
			if(locks_vio == 0)
			{
				sigaddset(&smask, SIGIO);
				has_changed = 1;
			}

			++locks_vio;
		}

		if(items & V_TIMER)
		{
			if(locks_vtimer == 0)
			{
				sigaddset(&smask, SIGALRM);
				has_changed = 1;
			}

			++locks_vtimer;
		}

		if(items & V_WINCH)
		{
			if(locks_vwinch == 0)
			{
				sigaddset(&smask, SIGWINCH);
				has_changed = 1;
			}

			++locks_vwinch;
		}

		if(has_changed)
		{
#if HAVE_SIGPROCMASK
			sigprocmask(SIG_BLOCK, &smask, NULL);
#else
			sigblock(smask);
#endif
		}
	}
	else if(mode == UNLOCK)
	{
		/*
		 * Unlock the given set of signals
		 * Signals are unlocked only if the last
		 * lock for the signal is removed and if
		 * no other instance had locked the signal
		 * before the first lock was made.
		 */

		sigemptyset(&smask);

		if(items & V_IO)
		{
			switch(locks_vio)
			{
				case 0:		break;
				case 1:		sigaddset(&smask, SIGIO);
						has_changed = locks_vio--;
						break;
				default:	--locks_vio;
						break;
			}
		}

		if(items & V_TIMER)
		{
			switch(locks_vtimer)
			{
				case 0:		break;
				case 1:		sigaddset(&smask, SIGALRM);
						has_changed = locks_vtimer--;
						break;
				default:	--locks_vtimer;
						break;
			}
		}

		if(items & V_WINCH)
		{
			switch(locks_vwinch)
			{
				case 0:		break;
				case 1:		sigaddset(&smask, SIGWINCH);
						has_changed = locks_vwinch--;
						break;
				default:	--locks_vwinch;
						break;
			}
		}

		if(has_changed)
		{
#if HAVE_SIGPROCMASK
			sigprocmask(SIG_UNBLOCK, &smask, NULL);
#else
			sigset_t tmp;

			tmp = sigblock(0);

			tmp &= ~smask;

			sigsetmask(tmp);
#endif
		}
	}
}

void async_io(int x)
{
	if(x)
	{
		fcntl(sconn.fd, F_SETOWN, getpid());
#if HAVE_STROPTS_H && HAVE_SYS_CONF_H
		ioctl(sconn.fd, I_SETSIG, S_RDNORM);
#elif defined(O_ASYNC)
	        fcntl(sconn.fd, F_SETFL, O_ASYNC);
#elif defined(FASYNC) 
	        fcntl(sconn.fd, F_SETFL, FASYNC);
#else
	        #error *** YOU BLEW IT! *** cannot determine how to set descriptors to async i/o
#endif  
	}
	else
	{
#if HAVE_STROPTS_H && HAVE_SYS_CONF_H
		ioctl(sconn.fd, I_SETSIG, 0);
#else
		fcntl(sconn.fd, F_SETFL, 0);
#endif
	}
}



syntax highlighted by Code2HTML, v. 0.9.1