131921Sbrian/*- 281957Sbrian * Copyright (c) 1997 - 1999, 2001 Brian Somers <brian@Awfulhak.org> 331921Sbrian * All rights reserved. 431921Sbrian * 531921Sbrian * Redistribution and use in source and binary forms, with or without 631921Sbrian * modification, are permitted provided that the following conditions 731921Sbrian * are met: 831921Sbrian * 1. Redistributions of source code must retain the above copyright 931921Sbrian * notice, this list of conditions and the following disclaimer. 1031921Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1131921Sbrian * notice, this list of conditions and the following disclaimer in the 1231921Sbrian * documentation and/or other materials provided with the distribution. 1331921Sbrian * 1431921Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1531921Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1631921Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1731921Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1831921Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1931921Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2031921Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2131921Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2231921Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2331921Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2431921Sbrian * SUCH DAMAGE. 2531921Sbrian * 2650479Speter * $FreeBSD$ 2723840Sbrian */ 2823840Sbrian 2997140Sbrian#include <sys/types.h> 3097140Sbrian 3123840Sbrian#include <signal.h> 3230715Sbrian 3323840Sbrian#include "log.h" 3431343Sbrian#include "sig.h" 3523840Sbrian 3634331Sbrianstatic int caused[NSIG]; /* An array of pending signals */ 3745126Sbrianstatic int necessary; /* Anything set ? */ 3823840Sbrianstatic sig_type handler[NSIG]; /* all start at SIG_DFL */ 3923840Sbrian 4023840Sbrian 4181957Sbrian/* 4281957Sbrian * Record a signal in the "caused" array 4381957Sbrian * 4481957Sbrian * This function is the only thing actually called in signal context. It 4581957Sbrian * records that a signal has been caused and that sig_Handle() should be 4681957Sbrian * called (in non-signal context) as soon as possible to process that 4781957Sbrian * signal. 4881957Sbrian */ 4928679Sbrianstatic void 5028679Sbriansignal_recorder(int sig) 5128679Sbrian{ 5228679Sbrian caused[sig - 1]++; 5345126Sbrian necessary = 1; 5423840Sbrian} 5523840Sbrian 5623840Sbrian 5723840Sbrian/* 5881957Sbrian * Set up signal_recorder to handle the given sig and record ``fn'' as 5981957Sbrian * the function to ultimately call in sig_Handle(). ``fn'' will not be 6081957Sbrian * called in signal context (as sig_Handle() is not called in signal 6181957Sbrian * context). 6281957Sbrian */ 6328679Sbriansig_type 6436285Sbriansig_signal(int sig, sig_type fn) 6528679Sbrian{ 6628679Sbrian sig_type Result; 6723840Sbrian 6828679Sbrian if (sig <= 0 || sig > NSIG) { 6928679Sbrian /* Oops - we must be a bit out of date (too many sigs ?) */ 7036285Sbrian log_Printf(LogALERT, "Eeek! %s:%d: I must be out of date!\n", 7128679Sbrian __FILE__, __LINE__); 7228679Sbrian return signal(sig, fn); 7328679Sbrian } 7428679Sbrian Result = handler[sig - 1]; 7528679Sbrian if (fn == SIG_DFL || fn == SIG_IGN) { 7628679Sbrian signal(sig, fn); 7728679Sbrian handler[sig - 1] = (sig_type) 0; 7828679Sbrian } else { 7928679Sbrian handler[sig - 1] = fn; 8028679Sbrian signal(sig, signal_recorder); 8128679Sbrian } 8228679Sbrian caused[sig - 1] = 0; 8328679Sbrian return Result; 8423840Sbrian} 8523840Sbrian 8623840Sbrian 8781957Sbrian/* 8881957Sbrian * Call the handlers for any pending signals 8981957Sbrian * 9081957Sbrian * This function is called from a non-signal context - in fact, it's 9181957Sbrian * called every time select() in DoLoop() returns - just in case 9281957Sbrian * select() returned due to a signal being recorded by signal_recorder(). 9381957Sbrian */ 9445126Sbrianint 9536285Sbriansig_Handle() 9628679Sbrian{ 9728679Sbrian int sig; 9828679Sbrian int got; 9945126Sbrian int result; 10023840Sbrian 10145126Sbrian result = 0; 10245126Sbrian if (necessary) { 10345126Sbrian /* We've *probably* got something in `caused' set */ 10445126Sbrian necessary = 0; 10545126Sbrian /* `necessary' might go back to 1 while we're in here.... */ 10645126Sbrian do { 10745126Sbrian got = 0; 10845126Sbrian for (sig = 0; sig < NSIG; sig++) 10945126Sbrian if (caused[sig]) { 11045126Sbrian caused[sig]--; 11145126Sbrian got++; 11245126Sbrian result++; 11345126Sbrian (*handler[sig])(sig + 1); 11445126Sbrian } 11545126Sbrian } while (got); 11645126Sbrian } 11745126Sbrian 11845126Sbrian return result; 11923840Sbrian} 120