136270Swpaul/*-
236270Swpaul * Copyright (c) 1997 - 1999, 2001 Brian Somers <brian@Awfulhak.org>
336270Swpaul * All rights reserved.
436270Swpaul *
536270Swpaul * Redistribution and use in source and binary forms, with or without
636270Swpaul * modification, are permitted provided that the following conditions
736270Swpaul * are met:
836270Swpaul * 1. Redistributions of source code must retain the above copyright
936270Swpaul *    notice, this list of conditions and the following disclaimer.
1036270Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1136270Swpaul *    notice, this list of conditions and the following disclaimer in the
1236270Swpaul *    documentation and/or other materials provided with the distribution.
1336270Swpaul *
1436270Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1536270Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1636270Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1736270Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1836270Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1936270Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2036270Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2136270Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2236270Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2336270Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2436270Swpaul * SUCH DAMAGE.
2536270Swpaul *
2636270Swpaul * $FreeBSD: releng/11.0/usr.sbin/ppp/sig.c 97140 2002-05-22 21:08:58Z brian $
2736270Swpaul */
2836270Swpaul
2936270Swpaul#include <sys/types.h>
3036270Swpaul
3136270Swpaul#include <signal.h>
3236302Swpaul
3336270Swpaul#include "log.h"
3436270Swpaul#include "sig.h"
3536270Swpaul
3636270Swpaulstatic int caused[NSIG];	/* An array of pending signals */
3736270Swpaulstatic int necessary;		/* Anything set ? */
3836270Swpaulstatic sig_type handler[NSIG];	/* all start at SIG_DFL */
3936270Swpaul
4036270Swpaul
4136270Swpaul/*
4236270Swpaul * Record a signal in the "caused" array
4336270Swpaul *
4436270Swpaul * This function is the only thing actually called in signal context.  It
4536270Swpaul * records that a signal has been caused and that sig_Handle() should be
4636270Swpaul * called (in non-signal context) as soon as possible to process that
4736270Swpaul * signal.
4836270Swpaul */
4936270Swpaulstatic void
5036270Swpaulsignal_recorder(int sig)
5136270Swpaul{
5236270Swpaul  caused[sig - 1]++;
5336270Swpaul  necessary = 1;
5436270Swpaul}
5536270Swpaul
5636270Swpaul
5736270Swpaul/*
5836270Swpaul * Set up signal_recorder to handle the given sig and record ``fn'' as
5936270Swpaul * the function to ultimately call in sig_Handle().  ``fn'' will not be
6036270Swpaul * called in signal context (as sig_Handle() is not called in signal
6136270Swpaul * context).
6236270Swpaul */
6336270Swpaulsig_type
6436270Swpaulsig_signal(int sig, sig_type fn)
6536270Swpaul{
6636270Swpaul  sig_type Result;
6736270Swpaul
6836270Swpaul  if (sig <= 0 || sig > NSIG) {
6936270Swpaul    /* Oops - we must be a bit out of date (too many sigs ?) */
7036270Swpaul    log_Printf(LogALERT, "Eeek! %s:%d: I must be out of date!\n",
7136270Swpaul	      __FILE__, __LINE__);
7236270Swpaul    return signal(sig, fn);
7336270Swpaul  }
7436270Swpaul  Result = handler[sig - 1];
7536270Swpaul  if (fn == SIG_DFL || fn == SIG_IGN) {
7636270Swpaul    signal(sig, fn);
7736270Swpaul    handler[sig - 1] = (sig_type) 0;
7836270Swpaul  } else {
7936270Swpaul    handler[sig - 1] = fn;
8036270Swpaul    signal(sig, signal_recorder);
8136270Swpaul  }
8236270Swpaul  caused[sig - 1] = 0;
8336270Swpaul  return Result;
8436270Swpaul}
8536270Swpaul
8636270Swpaul
8736270Swpaul/*
8836270Swpaul * Call the handlers for any pending signals
8936270Swpaul *
9036270Swpaul * This function is called from a non-signal context - in fact, it's
9136270Swpaul * called every time select() in DoLoop() returns - just in case
9236270Swpaul * select() returned due to a signal being recorded by signal_recorder().
9336270Swpaul */
9436270Swpaulint
9536270Swpaulsig_Handle()
9636270Swpaul{
9736270Swpaul  int sig;
9836270Swpaul  int got;
9936270Swpaul  int result;
10036270Swpaul
10136270Swpaul  result = 0;
10236270Swpaul  if (necessary) {
10336270Swpaul    /* We've *probably* got something in `caused' set */
10436270Swpaul    necessary = 0;
10536270Swpaul    /* `necessary' might go back to 1 while we're in here.... */
10636270Swpaul    do {
10736270Swpaul      got = 0;
10836270Swpaul      for (sig = 0; sig < NSIG; sig++)
10936270Swpaul        if (caused[sig]) {
11036270Swpaul	  caused[sig]--;
11136270Swpaul	  got++;
11236270Swpaul	  result++;
11336270Swpaul	  (*handler[sig])(sig + 1);
11436270Swpaul        }
11536270Swpaul    } while (got);
11636270Swpaul  }
11736270Swpaul
11836270Swpaul  return result;
11936270Swpaul}
12036270Swpaul