xref: /freebsd/usr.sbin/ppp/sig.c (revision 1de7b4b805ddbf2429da511c053686ac4591ed89)
1c39934eaSBrian Somers /*-
2*1de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*1de7b4b8SPedro F. Giffuni  *
4428217f7SBrian Somers  * Copyright (c) 1997 - 1999, 2001 Brian Somers <brian@Awfulhak.org>
5c39934eaSBrian Somers  * All rights reserved.
6c39934eaSBrian Somers  *
7c39934eaSBrian Somers  * Redistribution and use in source and binary forms, with or without
8c39934eaSBrian Somers  * modification, are permitted provided that the following conditions
9c39934eaSBrian Somers  * are met:
10c39934eaSBrian Somers  * 1. Redistributions of source code must retain the above copyright
11c39934eaSBrian Somers  *    notice, this list of conditions and the following disclaimer.
12c39934eaSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
13c39934eaSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
14c39934eaSBrian Somers  *    documentation and/or other materials provided with the distribution.
15c39934eaSBrian Somers  *
16c39934eaSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c39934eaSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c39934eaSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c39934eaSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c39934eaSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c39934eaSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c39934eaSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c39934eaSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c39934eaSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c39934eaSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c39934eaSBrian Somers  * SUCH DAMAGE.
27c39934eaSBrian Somers  *
2897d92980SPeter Wemm  * $FreeBSD$
29f5ff0f7cSBrian Somers  */
30f5ff0f7cSBrian Somers 
31b08bf2deSBrian Somers #include <sys/types.h>
32b08bf2deSBrian Somers 
33f5ff0f7cSBrian Somers #include <signal.h>
3475240ed1SBrian Somers 
35f5ff0f7cSBrian Somers #include "log.h"
36b6e82f33SBrian Somers #include "sig.h"
37f5ff0f7cSBrian Somers 
3874849645SBrian Somers static int caused[NSIG];	/* An array of pending signals */
39486105bcSBrian Somers static int necessary;		/* Anything set ? */
40f5ff0f7cSBrian Somers static sig_type handler[NSIG];	/* all start at SIG_DFL */
41f5ff0f7cSBrian Somers 
42f5ff0f7cSBrian Somers 
43428217f7SBrian Somers /*
44428217f7SBrian Somers  * Record a signal in the "caused" array
45428217f7SBrian Somers  *
46428217f7SBrian Somers  * This function is the only thing actually called in signal context.  It
47428217f7SBrian Somers  * records that a signal has been caused and that sig_Handle() should be
48428217f7SBrian Somers  * called (in non-signal context) as soon as possible to process that
49428217f7SBrian Somers  * signal.
50428217f7SBrian Somers  */
51944f7098SBrian Somers static void
52944f7098SBrian Somers signal_recorder(int sig)
53944f7098SBrian Somers {
54f5ff0f7cSBrian Somers   caused[sig - 1]++;
55486105bcSBrian Somers   necessary = 1;
56f5ff0f7cSBrian Somers }
57f5ff0f7cSBrian Somers 
58f5ff0f7cSBrian Somers 
59f5ff0f7cSBrian Somers /*
60428217f7SBrian Somers  * Set up signal_recorder to handle the given sig and record ``fn'' as
61428217f7SBrian Somers  * the function to ultimately call in sig_Handle().  ``fn'' will not be
62428217f7SBrian Somers  * called in signal context (as sig_Handle() is not called in signal
63428217f7SBrian Somers  * context).
64f5ff0f7cSBrian Somers  */
65944f7098SBrian Somers sig_type
66dd7e2610SBrian Somers sig_signal(int sig, sig_type fn)
67944f7098SBrian Somers {
68f5ff0f7cSBrian Somers   sig_type Result;
69f5ff0f7cSBrian Somers 
70f5ff0f7cSBrian Somers   if (sig <= 0 || sig > NSIG) {
71f5ff0f7cSBrian Somers     /* Oops - we must be a bit out of date (too many sigs ?) */
72dd7e2610SBrian Somers     log_Printf(LogALERT, "Eeek! %s:%d: I must be out of date!\n",
73927145beSBrian Somers 	      __FILE__, __LINE__);
74f5ff0f7cSBrian Somers     return signal(sig, fn);
75f5ff0f7cSBrian Somers   }
76f5ff0f7cSBrian Somers   Result = handler[sig - 1];
77f5ff0f7cSBrian Somers   if (fn == SIG_DFL || fn == SIG_IGN) {
78f5ff0f7cSBrian Somers     signal(sig, fn);
79f5ff0f7cSBrian Somers     handler[sig - 1] = (sig_type) 0;
80f5ff0f7cSBrian Somers   } else {
81f5ff0f7cSBrian Somers     handler[sig - 1] = fn;
82f5ff0f7cSBrian Somers     signal(sig, signal_recorder);
83f5ff0f7cSBrian Somers   }
84f5ff0f7cSBrian Somers   caused[sig - 1] = 0;
85f5ff0f7cSBrian Somers   return Result;
86f5ff0f7cSBrian Somers }
87f5ff0f7cSBrian Somers 
88f5ff0f7cSBrian Somers 
89428217f7SBrian Somers /*
90428217f7SBrian Somers  * Call the handlers for any pending signals
91428217f7SBrian Somers  *
92428217f7SBrian Somers  * This function is called from a non-signal context - in fact, it's
93428217f7SBrian Somers  * called every time select() in DoLoop() returns - just in case
94428217f7SBrian Somers  * select() returned due to a signal being recorded by signal_recorder().
95428217f7SBrian Somers  */
96486105bcSBrian Somers int
97dd7e2610SBrian Somers sig_Handle()
98944f7098SBrian Somers {
99f5ff0f7cSBrian Somers   int sig;
100f5ff0f7cSBrian Somers   int got;
101486105bcSBrian Somers   int result;
102f5ff0f7cSBrian Somers 
103486105bcSBrian Somers   result = 0;
104486105bcSBrian Somers   if (necessary) {
105486105bcSBrian Somers     /* We've *probably* got something in `caused' set */
106486105bcSBrian Somers     necessary = 0;
107486105bcSBrian Somers     /* `necessary' might go back to 1 while we're in here.... */
108f5ff0f7cSBrian Somers     do {
109f5ff0f7cSBrian Somers       got = 0;
110f5ff0f7cSBrian Somers       for (sig = 0; sig < NSIG; sig++)
111f5ff0f7cSBrian Somers         if (caused[sig]) {
112f5ff0f7cSBrian Somers 	  caused[sig]--;
113f5ff0f7cSBrian Somers 	  got++;
114486105bcSBrian Somers 	  result++;
115f5ff0f7cSBrian Somers 	  (*handler[sig])(sig + 1);
116f5ff0f7cSBrian Somers         }
117f5ff0f7cSBrian Somers     } while (got);
118f5ff0f7cSBrian Somers   }
119486105bcSBrian Somers 
120486105bcSBrian Somers   return result;
121486105bcSBrian Somers }
122