/******************************************************************************
* 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