2005-10-25 01:26:25 +10:00
/** \file event.c
2005-10-06 08:37:08 +10:00
2012-11-18 11:23:22 +01:00
Functions for handling event triggers
2005-10-06 08:37:08 +10:00
*/
2006-08-11 11:18:35 +10:00
# include "config.h"
2005-10-06 08:37:08 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
# include <unistd.h>
# include <termios.h>
# include <signal.h>
# include <string.h>
2011-12-26 22:18:16 -08:00
# include <algorithm>
2005-10-06 08:37:08 +10:00
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-10-06 08:37:08 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2006-01-21 00:27:21 +10:00
# include "wutil.h"
2005-10-06 08:37:08 +10:00
# include "function.h"
# include "proc.h"
# include "parser.h"
# include "common.h"
# include "event.h"
# include "signal.h"
2006-07-20 08:55:49 +10:00
2005-10-06 08:37:08 +10:00
/**
Number of signals that can be queued before an overflow occurs
*/
# define SIG_UNHANDLED_MAX 64
/**
This struct contains a list of generated signals waiting to be
dispatched
*/
typedef struct
{
2012-11-18 16:30:30 -08:00
/**
Number of delivered signals
*/
int count ;
/**
Whether signals have been skipped
*/
int overflow ;
/**
Array of signal events
*/
int signal [ SIG_UNHANDLED_MAX ] ;
2005-10-06 08:37:08 +10:00
}
2012-11-18 16:30:30 -08:00
signal_list_t ;
2005-10-06 08:37:08 +10:00
2005-10-25 01:26:25 +10:00
/**
2005-10-06 08:37:08 +10:00
The signal event list . Actually two separate lists . One which is
active , which is the one that new events is written to . The inactive
one contains the events that are currently beeing performed .
*/
2012-11-18 16:30:30 -08:00
static signal_list_t sig_list [ ] = { { 0 , 0 } , { 0 , 0 } } ;
2005-10-06 08:37:08 +10:00
/**
The index of sig_list that is the list of signals currently written to
*/
static int active_list = 0 ;
2012-11-18 11:23:22 +01:00
typedef std : : vector < event_t * > event_list_t ;
2011-12-26 22:27:58 -08:00
2005-10-06 08:37:08 +10:00
/**
2012-06-04 14:20:01 -07:00
List of event handlers .
Note this is inspected by our signal handler , so we must block signals around manipulating it .
2005-10-06 08:37:08 +10:00
*/
2011-12-26 22:27:58 -08:00
static event_list_t events ;
2005-10-06 08:37:08 +10:00
/**
List of event handlers that should be removed
*/
2011-12-26 22:27:58 -08:00
static event_list_t killme ;
2005-10-06 08:37:08 +10:00
2005-12-12 08:21:01 +10:00
/**
List of events that have been sent but have not yet been delivered because they are blocked .
*/
2011-12-26 22:27:58 -08:00
static event_list_t blocked ;
2005-12-12 08:21:01 +10:00
2005-10-06 08:37:08 +10:00
/**
Tests if one event instance matches the definition of a event
2006-02-03 01:33:30 +10:00
class . If both the class and the instance name a function ,
they must name the same function .
2005-10-06 08:37:08 +10:00
*/
2012-11-18 16:30:30 -08:00
static int event_match ( const event_t * classv , const event_t * instance )
2005-10-06 08:37:08 +10:00
{
2007-08-20 02:42:30 +10:00
2012-03-05 14:18:16 -08:00
/* If the function names are both non-empty and different, then it's not a match */
2012-11-18 16:30:30 -08:00
if ( ! classv - > function_name . empty ( ) & &
! instance - > function_name . empty ( ) & &
classv - > function_name ! = instance - > function_name )
{
2012-03-05 14:18:16 -08:00
return 0 ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( classv - > type = = EVENT_ANY )
return 1 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( classv - > type ! = instance - > type )
return 0 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
switch ( classv - > type )
{
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_SIGNAL :
if ( classv - > param1 . signal = = EVENT_ANY_SIGNAL )
return 1 ;
return classv - > param1 . signal = = instance - > param1 . signal ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_VARIABLE :
return instance - > str_param1 = = classv - > str_param1 ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_EXIT :
if ( classv - > param1 . pid = = EVENT_ANY_PID )
return 1 ;
return classv - > param1 . pid = = instance - > param1 . pid ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_JOB_ID :
return classv - > param1 . job_id = = instance - > param1 . job_id ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_GENERIC :
return instance - > str_param1 = = classv - > str_param1 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/**
This should never be reached
*/
return 0 ;
2005-10-06 08:37:08 +10:00
}
/**
Create an identical copy of an event . Use deep copying , i . e . make
duplicates of any strings used as well .
*/
2012-11-18 16:30:30 -08:00
static event_t * event_copy ( const event_t * event , int copy_arguments )
2005-10-06 08:37:08 +10:00
{
2012-02-08 19:02:25 -08:00
event_t * e = new event_t ( * event ) ;
2012-11-18 11:23:22 +01:00
2012-02-08 19:02:25 -08:00
e - > arguments . reset ( new wcstring_list_t ) ;
2012-11-18 16:30:30 -08:00
if ( copy_arguments & & event - > arguments . get ( ) ! = NULL )
{
2012-11-18 11:23:22 +01:00
* ( e - > arguments ) = * ( event - > arguments ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return e ;
2005-10-06 08:37:08 +10:00
}
2006-01-24 06:40:14 +10:00
/**
Test if specified event is blocked
*/
2012-11-18 16:30:30 -08:00
static int event_is_blocked ( event_t * e )
2005-12-12 08:21:01 +10:00
{
2012-11-18 16:30:30 -08:00
block_t * block ;
parser_t & parser = parser_t : : principal_parser ( ) ;
for ( block = parser . current_block ; block ; block = block - > outer )
{
2012-02-07 21:04:51 -08:00
if ( event_block_list_blocks_type ( block - > event_blocks , e - > type ) )
return true ;
2012-11-18 16:30:30 -08:00
}
2012-02-07 21:04:51 -08:00
return event_block_list_blocks_type ( parser . global_event_blocks , e - > type ) ;
2005-12-12 08:21:01 +10:00
}
2012-11-18 16:30:30 -08:00
wcstring event_get_desc ( const event_t * e )
2006-02-02 01:49:11 +10:00
{
2006-06-21 20:07:46 +10:00
2012-11-18 16:30:30 -08:00
CHECK ( e , 0 ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
wcstring result ;
switch ( e - > type )
{
2006-06-21 20:07:46 +10:00
2012-11-19 00:31:03 -08:00
case EVENT_SIGNAL :
result = format_string ( _ ( L " signal handler for %ls (%ls) " ) , sig2wcs ( e - > param1 . signal ) , signal_get_desc ( e - > param1 . signal ) ) ;
break ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_VARIABLE :
result = format_string ( _ ( L " handler for variable '%ls' " ) , e - > str_param1 . c_str ( ) ) ;
break ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_EXIT :
if ( e - > param1 . pid > 0 )
{
result = format_string ( _ ( L " exit handler for process %d " ) , e - > param1 . pid ) ;
}
else
{
job_t * j = job_get_from_pid ( - e - > param1 . pid ) ;
if ( j )
result = format_string ( _ ( L " exit handler for job %d, '%ls' " ) , j - > job_id , j - > command_wcstr ( ) ) ;
else
result = format_string ( _ ( L " exit handler for job with process group %d " ) , - e - > param1 . pid ) ;
}
break ;
case EVENT_JOB_ID :
2012-11-18 16:30:30 -08:00
{
2012-11-19 00:31:03 -08:00
job_t * j = job_get ( e - > param1 . job_id ) ;
2012-11-18 16:30:30 -08:00
if ( j )
result = format_string ( _ ( L " exit handler for job %d, '%ls' " ) , j - > job_id , j - > command_wcstr ( ) ) ;
else
2012-11-19 00:31:03 -08:00
result = format_string ( _ ( L " exit handler for job with job id %d " ) , e - > param1 . job_id ) ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
break ;
}
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case EVENT_GENERIC :
result = format_string ( _ ( L " handler for generic event '%ls' " ) , e - > str_param1 . c_str ( ) ) ;
break ;
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
default :
result = format_string ( _ ( L " Unknown event type " ) ) ;
break ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return result ;
2006-02-02 01:49:11 +10:00
}
2012-02-17 15:58:02 -08:00
#if 0
2012-11-18 16:30:30 -08:00
static void show_all_handlers ( void )
{
2012-02-17 11:36:49 -08:00
puts ( " event handlers: " ) ;
2012-11-18 16:30:30 -08:00
for ( event_list_t : : const_iterator iter = events . begin ( ) ; iter ! = events . end ( ) ; + + iter )
{
2012-02-17 11:36:49 -08:00
const event_t * foo = * iter ;
wcstring tmp = event_get_desc ( foo ) ;
printf ( " handler now %ls \n " , tmp . c_str ( ) ) ;
}
}
2012-02-17 15:58:02 -08:00
# endif
2005-12-12 08:21:01 +10:00
2012-11-18 16:30:30 -08:00
void event_add_handler ( const event_t * event )
2005-10-06 08:37:08 +10:00
{
2012-11-18 16:30:30 -08:00
event_t * e ;
2005-12-12 08:21:01 +10:00
2012-11-18 16:30:30 -08:00
CHECK ( event , ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
e = event_copy ( event , 0 ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( e - > type = = EVENT_SIGNAL )
{
signal_handle ( e - > param1 . signal , 1 ) ;
}
2005-10-06 08:37:08 +10:00
2012-06-04 14:20:01 -07:00
// Block around updating the events vector
signal_block ( ) ;
events . push_back ( e ) ;
signal_unblock ( ) ;
2005-10-06 08:37:08 +10:00
}
2012-11-18 16:30:30 -08:00
void event_remove ( event_t * criterion )
2005-10-06 08:37:08 +10:00
{
2012-02-17 11:36:49 -08:00
2012-11-18 16:30:30 -08:00
size_t i ;
event_list_t new_list ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
CHECK ( criterion , ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
Because of concurrency issues ( env_remove could remove an event
that is currently being executed ) , env_remove does not actually
free any events - instead it simply moves all events that should
be removed from the event list to the killme list , and the ones
that shouldn ' t be killed to new_list , and then drops the empty
events - list .
*/
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( events . empty ( ) )
return ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < events . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
event_t * n = events . at ( i ) ;
if ( event_match ( criterion , n ) )
{
2011-12-26 22:22:55 -08:00
killme . push_back ( n ) ;
2005-10-06 21:54:16 +10:00
2012-11-18 16:30:30 -08:00
/*
If this event was a signal handler and no other handler handles
the specified signal type , do not handle that type of signal any
more .
*/
if ( n - > type = = EVENT_SIGNAL )
{
2012-02-08 19:02:25 -08:00
event_t e = event_t : : signal_event ( n - > param1 . signal ) ;
2012-11-18 16:30:30 -08:00
if ( event_get ( & e , 0 ) = = 1 )
{
signal_handle ( e . param1 . signal , 0 ) ;
}
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
else
{
2011-12-26 22:18:16 -08:00
new_list . push_back ( n ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2012-06-04 14:20:01 -07:00
signal_block ( ) ;
2012-11-18 16:30:30 -08:00
events . swap ( new_list ) ;
2012-06-04 14:20:01 -07:00
signal_unblock ( ) ;
2005-10-06 08:37:08 +10:00
}
2012-11-18 16:30:30 -08:00
int event_get ( event_t * criterion , std : : vector < event_t * > * out )
2005-10-06 08:37:08 +10:00
{
2012-11-18 16:30:30 -08:00
size_t i ;
int found = 0 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( events . empty ( ) )
return 0 ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
CHECK ( criterion , 0 ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < events . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
event_t * n = events . at ( i ) ;
if ( event_match ( criterion , n ) )
{
found + + ;
if ( out )
2012-02-07 17:06:45 -08:00
out - > push_back ( n ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
return found ;
2005-10-06 08:37:08 +10:00
}
2012-06-04 14:20:01 -07:00
bool event_is_signal_observed ( int sig )
{
/* We are in a signal handler! Don't allocate memory, etc.
This does what event_match does , except it doesn ' t require passing in an event_t .
*/
size_t i , max = events . size ( ) ;
for ( i = 0 ; i < max ; i + + )
{
const event_t * event = events [ i ] ;
if ( event - > type = = EVENT_ANY )
{
return true ;
}
else if ( event - > type = = EVENT_SIGNAL )
{
2012-11-18 16:30:30 -08:00
if ( event - > param1 . signal = = EVENT_ANY_SIGNAL | | event - > param1 . signal = = sig )
2012-06-04 14:20:01 -07:00
return true ;
}
}
return false ;
}
2005-10-06 08:37:08 +10:00
/**
Free all events in the kill list
*/
static void event_free_kills ( )
{
2011-12-26 22:22:55 -08:00
for_each ( killme . begin ( ) , killme . end ( ) , event_free ) ;
killme . resize ( 0 ) ;
2005-10-06 08:37:08 +10:00
}
/**
Test if the specified event is waiting to be killed
*/
2012-11-18 16:30:30 -08:00
static int event_is_killed ( event_t * e )
2005-10-06 08:37:08 +10:00
{
2011-12-26 22:22:55 -08:00
return std : : find ( killme . begin ( ) , killme . end ( ) , e ) ! = killme . end ( ) ;
2012-11-18 11:23:22 +01:00
}
2005-10-06 08:37:08 +10:00
/**
Perform the specified event . Since almost all event firings will
2006-07-30 03:31:59 +10:00
not be matched by even a single event handler , we make sure to
optimize the ' no matches ' path . This means that nothing is
allocated / initialized unless needed .
2005-10-06 08:37:08 +10:00
*/
2012-11-18 16:30:30 -08:00
static void event_fire_internal ( const event_t * event )
2005-10-06 08:37:08 +10:00
{
2012-02-17 11:36:49 -08:00
2012-11-18 16:30:30 -08:00
size_t i , j ;
event_list_t fire ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
First we free all events that have been removed
*/
event_free_kills ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( events . empty ( ) )
return ;
2012-11-18 11:23:22 +01:00
/*
2012-11-18 16:30:30 -08:00
Then we iterate over all events , adding events that should be
fired to a second list . We need to do this in a separate step
since an event handler might call event_remove or
event_add_handler , which will change the contents of the \ c
events list .
2012-11-18 11:23:22 +01:00
*/
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < events . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
event_t * criterion = events . at ( i ) ;
/*
Check if this event is a match
*/
if ( event_match ( criterion , event ) )
{
2011-12-26 22:51:34 -08:00
fire . push_back ( criterion ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
/*
2012-11-18 16:30:30 -08:00
No matches . Time to return .
2012-11-18 11:23:22 +01:00
*/
2012-11-18 16:30:30 -08:00
if ( fire . empty ( ) )
return ;
2012-11-18 11:23:22 +01:00
/*
2012-11-18 16:30:30 -08:00
Iterate over our list of matching events
2012-11-18 11:23:22 +01:00
*/
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < fire . size ( ) ; i + + )
{
event_t * criterion = fire . at ( i ) ;
int prev_status ;
/*
Check if this event has been removed , if so , dont fire it
*/
if ( event_is_killed ( criterion ) )
continue ;
/*
Fire event
*/
wcstring buffer = criterion - > function_name ;
2012-11-18 11:23:22 +01:00
2012-02-08 19:02:25 -08:00
if ( event - > arguments . get ( ) )
2011-12-27 00:06:07 -08:00
{
2012-11-18 16:30:30 -08:00
for ( j = 0 ; j < event - > arguments - > size ( ) ; j + + )
2011-12-27 00:06:07 -08:00
{
2012-11-18 16:30:30 -08:00
wcstring arg_esc = escape_string ( event - > arguments - > at ( j ) , 1 ) ;
2011-12-27 00:06:07 -08:00
buffer + = L " " ;
buffer + = arg_esc ;
}
}
2005-10-12 05:23:43 +10:00
2012-11-18 11:23:22 +01:00
// debug( 1, L"Event handler fires command '%ls'", buffer.c_str() );
2012-11-18 16:30:30 -08:00
/*
Event handlers are not part of the main flow of code , so
they are marked as non - interactive
*/
proc_push_interactive ( 0 ) ;
prev_status = proc_get_last_status ( ) ;
2012-01-22 21:40:08 -08:00
parser_t & parser = parser_t : : principal_parser ( ) ;
2012-11-18 11:23:22 +01:00
2012-08-26 22:42:29 -07:00
block_t * block = new event_block_t ( event ) ;
2012-11-18 16:30:30 -08:00
parser . push_block ( block ) ;
parser . eval ( buffer , io_chain_t ( ) , TOP ) ;
parser . pop_block ( ) ;
proc_pop_interactive ( ) ;
proc_set_last_status ( prev_status ) ;
}
/*
Free killed events
*/
event_free_kills ( ) ;
2012-11-18 11:23:22 +01:00
2005-10-06 08:37:08 +10:00
}
/**
2005-10-15 10:51:26 +10:00
Handle all pending signal events
2005-10-06 08:37:08 +10:00
*/
2005-12-12 08:21:01 +10:00
static void event_fire_delayed ( )
2005-10-06 08:37:08 +10:00
{
2005-12-12 08:21:01 +10:00
2012-11-18 16:30:30 -08:00
size_t i ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
If is_event is one , we are running the event - handler non - recursively .
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
When the event handler has called a piece of code that triggers
another event , we do not want to fire delayed events because of
concurrency problems .
*/
if ( ! blocked . empty ( ) & & is_event = = 1 )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
event_list_t new_blocked ;
for ( i = 0 ; i < blocked . size ( ) ; i + + )
{
event_t * e = blocked . at ( i ) ;
if ( event_is_blocked ( e ) )
{
2011-12-26 22:27:58 -08:00
new_blocked . push_back ( e ) ;
2012-11-18 16:30:30 -08:00
}
else
{
event_fire_internal ( e ) ;
event_free ( e ) ;
}
}
2011-12-26 22:27:58 -08:00
blocked . swap ( new_blocked ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
while ( sig_list [ active_list ] . count > 0 )
{
signal_list_t * lst ;
/*
Switch signal lists
*/
sig_list [ 1 - active_list ] . count = 0 ;
sig_list [ 1 - active_list ] . overflow = 0 ;
active_list = 1 - active_list ;
/*
Set up
*/
2012-02-08 19:02:25 -08:00
event_t e = event_t : : signal_event ( 0 ) ;
e . arguments . reset ( new wcstring_list_t ( 1 ) ) ; //one element
2012-11-18 16:30:30 -08:00
lst = & sig_list [ 1 - active_list ] ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( lst - > overflow )
{
debug ( 0 , _ ( L " Signal list overflow. Signals have been ignored. " ) ) ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
Send all signals in our private list
*/
for ( int i = 0 ; i < lst - > count ; i + + )
{
e . param1 . signal = lst - > signal [ i ] ;
e . arguments - > at ( 0 ) = sig2wcs ( e . param1 . signal ) ;
if ( event_is_blocked ( & e ) )
{
2011-12-26 22:27:58 -08:00
blocked . push_back ( event_copy ( & e , 1 ) ) ;
2012-11-18 16:30:30 -08:00
}
else
{
event_fire_internal ( & e ) ;
}
}
2012-11-18 11:23:22 +01:00
2012-02-08 19:02:25 -08:00
e . arguments . reset ( NULL ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2005-10-06 08:37:08 +10:00
}
2012-06-04 14:20:01 -07:00
void event_fire_signal ( int signal )
{
/*
This means we are in a signal handler . We must be very
careful not do do anything that could cause a memory
allocation or something else that might be bad when in a
signal handler .
*/
2012-11-18 16:30:30 -08:00
if ( sig_list [ active_list ] . count < SIG_UNHANDLED_MAX )
2012-06-04 14:20:01 -07:00
sig_list [ active_list ] . signal [ sig_list [ active_list ] . count + + ] = signal ;
else
sig_list [ active_list ] . overflow = 1 ;
}
2005-10-06 08:37:08 +10:00
2012-11-18 16:30:30 -08:00
void event_fire ( event_t * event )
2005-10-06 08:37:08 +10:00
{
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( event & & ( event - > type = = EVENT_SIGNAL ) )
{
2012-06-04 14:20:01 -07:00
event_fire_signal ( event - > param1 . signal ) ;
2012-11-18 16:30:30 -08:00
}
else
{
2012-06-04 14:20:01 -07:00
is_event + + ;
2012-11-18 16:30:30 -08:00
/*
Fire events triggered by signals
*/
event_fire_delayed ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( event )
{
if ( event_is_blocked ( event ) )
{
2011-12-26 22:27:58 -08:00
blocked . push_back ( event_copy ( event , 1 ) ) ;
2012-11-18 16:30:30 -08:00
}
else
{
event_fire_internal ( event ) ;
}
}
2012-06-04 14:20:01 -07:00
is_event - - ;
2012-11-18 16:30:30 -08:00
}
2005-10-06 08:37:08 +10:00
}
void event_init ( )
{
}
void event_destroy ( )
{
2006-02-06 23:45:32 +10:00
2011-12-26 22:18:16 -08:00
for_each ( events . begin ( ) , events . end ( ) , event_free ) ;
2012-06-04 14:20:01 -07:00
events . clear ( ) ;
2012-11-18 11:23:22 +01:00
2011-12-26 22:22:55 -08:00
for_each ( killme . begin ( ) , killme . end ( ) , event_free ) ;
2012-06-04 14:20:01 -07:00
killme . clear ( ) ;
2005-10-06 08:37:08 +10:00
}
2012-11-18 16:30:30 -08:00
void event_free ( event_t * e )
2005-10-06 08:37:08 +10:00
{
2012-11-18 16:30:30 -08:00
CHECK ( e , ) ;
2012-02-08 19:02:25 -08:00
delete e ;
2005-10-06 08:37:08 +10:00
}
2006-05-14 20:16:23 +10:00
2007-08-20 02:42:30 +10:00
2008-01-15 08:31:24 +10:00
void event_fire_generic_internal ( const wchar_t * name , . . . )
2007-08-20 02:42:30 +10:00
{
2012-11-18 16:30:30 -08:00
va_list va ;
wchar_t * arg ;
2007-08-20 02:42:30 +10:00
2012-11-18 16:30:30 -08:00
CHECK ( name , ) ;
2012-02-08 19:02:25 -08:00
2012-11-18 16:30:30 -08:00
event_t ev ( EVENT_GENERIC ) ;
ev . str_param1 = name ;
2012-02-08 19:02:25 -08:00
ev . arguments . reset ( new wcstring_list_t ) ;
2012-11-18 16:30:30 -08:00
va_start ( va , name ) ;
while ( ( arg = va_arg ( va , wchar_t * ) ) ! = 0 )
{
2011-12-27 00:06:07 -08:00
ev . arguments - > push_back ( arg ) ;
2012-11-18 16:30:30 -08:00
}
va_end ( va ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
event_fire ( & ev ) ;
2012-02-08 19:02:25 -08:00
ev . arguments . reset ( NULL ) ;
2007-08-20 02:42:30 +10:00
}
2012-11-18 16:30:30 -08:00
event_t event_t : : signal_event ( int sig )
{
2012-02-08 19:02:25 -08:00
event_t event ( EVENT_SIGNAL ) ;
event . param1 . signal = sig ;
return event ;
}
2007-08-20 02:42:30 +10:00
2012-11-18 16:30:30 -08:00
event_t event_t : : variable_event ( const wcstring & str )
{
2012-02-08 19:02:25 -08:00
event_t event ( EVENT_VARIABLE ) ;
event . str_param1 = str ;
return event ;
}
2012-11-18 16:30:30 -08:00
event_t event_t : : generic_event ( const wcstring & str )
{
2012-02-08 19:02:25 -08:00
event_t event ( EVENT_GENERIC ) ;
event . str_param1 = str ;
return event ;
}
event_t : : event_t ( const event_t & x ) :
2012-11-18 16:30:30 -08:00
type ( x . type ) ,
param1 ( x . param1 ) ,
str_param1 ( x . str_param1 ) ,
function_name ( x . function_name )
2012-02-08 19:02:25 -08:00
{
const wcstring_list_t * ptr = x . arguments . get ( ) ;
if ( ptr )
arguments . reset ( new wcstring_list_t ( * ptr ) ) ;
}