131921Sbrian/*-
2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3330449Seadler *
481957Sbrian * Copyright (c) 1997 - 1999, 2001 Brian Somers <brian@Awfulhak.org>
531921Sbrian * All rights reserved.
631921Sbrian *
731921Sbrian * Redistribution and use in source and binary forms, with or without
831921Sbrian * modification, are permitted provided that the following conditions
931921Sbrian * are met:
1031921Sbrian * 1. Redistributions of source code must retain the above copyright
1131921Sbrian *    notice, this list of conditions and the following disclaimer.
1231921Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1331921Sbrian *    notice, this list of conditions and the following disclaimer in the
1431921Sbrian *    documentation and/or other materials provided with the distribution.
1531921Sbrian *
1631921Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1731921Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1831921Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1931921Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2031921Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2131921Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2231921Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2331921Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2431921Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2531921Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2631921Sbrian * SUCH DAMAGE.
2731921Sbrian *
2850479Speter * $FreeBSD: stable/11/usr.sbin/ppp/sig.c 330449 2018-03-05 07:26:05Z eadler $
2923840Sbrian */
3023840Sbrian
3197140Sbrian#include <sys/types.h>
3297140Sbrian
3323840Sbrian#include <signal.h>
3430715Sbrian
3523840Sbrian#include "log.h"
3631343Sbrian#include "sig.h"
3723840Sbrian
3834331Sbrianstatic int caused[NSIG];	/* An array of pending signals */
3945126Sbrianstatic int necessary;		/* Anything set ? */
4023840Sbrianstatic sig_type handler[NSIG];	/* all start at SIG_DFL */
4123840Sbrian
4223840Sbrian
4381957Sbrian/*
4481957Sbrian * Record a signal in the "caused" array
4581957Sbrian *
4681957Sbrian * This function is the only thing actually called in signal context.  It
4781957Sbrian * records that a signal has been caused and that sig_Handle() should be
4881957Sbrian * called (in non-signal context) as soon as possible to process that
4981957Sbrian * signal.
5081957Sbrian */
5128679Sbrianstatic void
5228679Sbriansignal_recorder(int sig)
5328679Sbrian{
5428679Sbrian  caused[sig - 1]++;
5545126Sbrian  necessary = 1;
5623840Sbrian}
5723840Sbrian
5823840Sbrian
5923840Sbrian/*
6081957Sbrian * Set up signal_recorder to handle the given sig and record ``fn'' as
6181957Sbrian * the function to ultimately call in sig_Handle().  ``fn'' will not be
6281957Sbrian * called in signal context (as sig_Handle() is not called in signal
6381957Sbrian * context).
6481957Sbrian */
6528679Sbriansig_type
6636285Sbriansig_signal(int sig, sig_type fn)
6728679Sbrian{
6828679Sbrian  sig_type Result;
6923840Sbrian
7028679Sbrian  if (sig <= 0 || sig > NSIG) {
7128679Sbrian    /* Oops - we must be a bit out of date (too many sigs ?) */
7236285Sbrian    log_Printf(LogALERT, "Eeek! %s:%d: I must be out of date!\n",
7328679Sbrian	      __FILE__, __LINE__);
7428679Sbrian    return signal(sig, fn);
7528679Sbrian  }
7628679Sbrian  Result = handler[sig - 1];
7728679Sbrian  if (fn == SIG_DFL || fn == SIG_IGN) {
7828679Sbrian    signal(sig, fn);
7928679Sbrian    handler[sig - 1] = (sig_type) 0;
8028679Sbrian  } else {
8128679Sbrian    handler[sig - 1] = fn;
8228679Sbrian    signal(sig, signal_recorder);
8328679Sbrian  }
8428679Sbrian  caused[sig - 1] = 0;
8528679Sbrian  return Result;
8623840Sbrian}
8723840Sbrian
8823840Sbrian
8981957Sbrian/*
9081957Sbrian * Call the handlers for any pending signals
9181957Sbrian *
9281957Sbrian * This function is called from a non-signal context - in fact, it's
9381957Sbrian * called every time select() in DoLoop() returns - just in case
9481957Sbrian * select() returned due to a signal being recorded by signal_recorder().
9581957Sbrian */
9645126Sbrianint
9736285Sbriansig_Handle()
9828679Sbrian{
9928679Sbrian  int sig;
10028679Sbrian  int got;
10145126Sbrian  int result;
10223840Sbrian
10345126Sbrian  result = 0;
10445126Sbrian  if (necessary) {
10545126Sbrian    /* We've *probably* got something in `caused' set */
10645126Sbrian    necessary = 0;
10745126Sbrian    /* `necessary' might go back to 1 while we're in here.... */
10845126Sbrian    do {
10945126Sbrian      got = 0;
11045126Sbrian      for (sig = 0; sig < NSIG; sig++)
11145126Sbrian        if (caused[sig]) {
11245126Sbrian	  caused[sig]--;
11345126Sbrian	  got++;
11445126Sbrian	  result++;
11545126Sbrian	  (*handler[sig])(sig + 1);
11645126Sbrian        }
11745126Sbrian    } while (got);
11845126Sbrian  }
11945126Sbrian
12045126Sbrian  return result;
12123840Sbrian}
122