/************************************************************************
 * ptimer.c                                                             *
 *                                                                      *
 * Copyright (C) 2002 - 2020 Joshua Birnbaum <engineer@noorg.org>.      *
 * All Rights Reserved.                                                 *
 *                                                                      *
 * This program is free software; you can redistribute it and/or modify *
 * it under the terms of the GNU General Public License as published    *
 * by the Free Software Foundation; either version 2 of the License, or *
 * (at your option) any later version.                                  *
 *                                                                      *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS    *
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED    *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE   *
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY      *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL   *
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE    *
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS        *
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,         *
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING            *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         *
 *                                                                      *
 * You should have received a copy of the GNU General Public License    *
 * along with this program; see the file COPYING. If not, write to the  *
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
 * MA 02111-1307, USA.                                                  *
 ************************************************************************/

/****************************************************************
 * Project ifchk -- Host based network interface promiscuous    *
 *                  mode detection and handling.                *
 *                                                              *
 * Version:         1.1.2                                       *
 *                                                              *
 * ------------------------------------------------------------ *
 *                                                              *
 * psig.c:          ifchk posix timer routines.                 *
 *                                                              *
 * Module                                                       *
 * Functions:     - Initializes and arms our POSIX timers.      *
 *                - Counts down, one second at a time, to zero. *
 *                - Sends SIGUSR1, SIGUSR2 to ourselves upon    *
 *                  timer expiration (when we reach 0 seconds.) *
 ****************************************************************/

/**********************
 * include directives *
 **********************/

#include "ptimer.h"


/***********************
 * global declarations *
 ***********************/

struct sigevent evpTimer;
timer_t timerOne = 0;
timer_t timerTwo = 0;
struct itimerspec spec;


/*************************************************************
 * pTimerInit() - Initialize and arm POSIX timers.           *
 *                                                           *
 * Parameters:    ifStatSecs: Countdown ifStatusSecs seconds *
 *                            before initiating a network    *
 *                            interface status scan.         *
 *                                                           *
 * Parameters:    ifMetSecs:  Countdown ifMetSecs seconds    *
 *                            before initiating a network    *
 *                            interface metrics scan.        *
 *                                                           *
 * Returns:       0 on success.                              *
 *                -1 on failure.                             *
 *************************************************************/

int pTimerInit( int ifStatSecs, int ifMetSecs)
{
    /*
     * Create a POSIX interval timer to send SIGUSR1 to ourselves.
     * This timer triggers network interface status scans.
     */
    evpTimer.sigev_notify = SIGEV_SIGNAL;
    evpTimer.sigev_signo = SIGUSR1;

    if( timer_create( CLOCK_REALTIME, &evpTimer, &timerOne ) != 0 )
    {
        errHandler( "ERROR: timer_create(): could not create interval timer: %s\n",
                                                                  strerror( errno ) );
        exit( EXIT_FAILURE );
     }

    /*
     * Specify that initially, the SIGUSR1 timer will fire one second after
     * being armed and then every ifStatusSecs (user defined) thereafter.
     */
    spec.it_value.tv_sec = 1;
    spec.it_value.tv_nsec = 0;
    spec.it_interval.tv_sec = ifStatSecs;
    spec.it_interval.tv_nsec = 0;

    /*
     * Arm the SIGUSR1 timer.
     */
    if( timer_settime( timerOne, 0, &spec, NULL ) != 0 )
    {
        errHandler( "ERROR: timer_settime(): could not arm interval timer: %s\n",
                                                                strerror( errno ) );
        exit( EXIT_FAILURE );
     }

    /*
     * Create a POSIX interval timer to send SIGUSR2 to ourselves.
     * This timer triggers network interface metrics dumps.
     */
    evpTimer.sigev_notify = SIGEV_SIGNAL;
    evpTimer.sigev_signo = SIGUSR2;

    if( timer_create( CLOCK_REALTIME, &evpTimer, &timerTwo ) != 0 )
    {
        errHandler( "ERROR: timer_create(): could not create interval timer: %s\n",
                                                                  strerror( errno ) );
        exit( EXIT_FAILURE );
     }

    /*
     * Specify that initially, the SIGUSR2 timer will fire one second after
     * being armed and then every ifMetricSecs (user defined) thereafter.
     */
    spec.it_value.tv_sec = 1;
    spec.it_value.tv_nsec = 0;
    spec.it_interval.tv_sec = ifMetSecs;
    spec.it_interval.tv_nsec = 0;

    /*
     * Arm the SIGUSR2 timer.
     */
    if( timer_settime( timerTwo, 0, &spec, NULL ) != 0 )
    {
        errHandler( "ERROR: timer_settime(): could not arm interval timer: %s\n",
                                                                strerror( errno ) );
        exit( EXIT_FAILURE );
     }

    return (0);
}
