| 
									
										
										
										
											2009-05-27 09:50:13 +02:00
										 |  |  | #include "sigchain.h"
 | 
					
						
							|  |  |  | #include "cache.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SIGCHAIN_MAX_SIGNALS 32
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sigchain_signal { | 
					
						
							|  |  |  | 	sigchain_fun *old; | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	int alloc; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void check_signum(int sig) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) | 
					
						
							|  |  |  | 		die("BUG: signal out of range: %d", sig); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-18 18:29:23 -03:00
										 |  |  | static int sigchain_push(int sig, sigchain_fun f) | 
					
						
							| 
									
										
										
										
											2009-05-27 09:50:13 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct sigchain_signal *s = signals + sig; | 
					
						
							|  |  |  | 	check_signum(sig); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ALLOC_GROW(s->old, s->n + 1, s->alloc); | 
					
						
							|  |  |  | 	s->old[s->n] = signal(sig, f); | 
					
						
							|  |  |  | 	if (s->old[s->n] == SIG_ERR) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	s->n++; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int sigchain_pop(int sig) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sigchain_signal *s = signals + sig; | 
					
						
							|  |  |  | 	check_signum(sig); | 
					
						
							|  |  |  | 	if (s->n < 1) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (signal(sig, s->old[s->n - 1]) == SIG_ERR) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	s->n--; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void sigchain_push_common(sigchain_fun f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	sigchain_push(SIGINT, f); | 
					
						
							|  |  |  | 	sigchain_push(SIGHUP, f); | 
					
						
							|  |  |  | 	sigchain_push(SIGTERM, f); | 
					
						
							|  |  |  | 	sigchain_push(SIGQUIT, f); | 
					
						
							|  |  |  | 	sigchain_push(SIGPIPE, f); | 
					
						
							|  |  |  | } |