/* functions for signal handling */
/* ----------------------------- */

#include "headers.h" /* all important stuff */ 

/* handle various signals */
RETSIGTYPE sighandler(int sig)
{
   int oerrno = errno; /* save old errno */

   (void)signal(SIGPIPE, SIG_IGN);

   /* need local scope variables here.. */
   if (debugging == 1)
   {
      char *line = "-------------------------------------------------";
      char *error = "\nsignal handler called.. ";     

      (void)write(STDOUT, line, strlen(line));
      (void)write(STDOUT, error, strlen(error));

      (void)printf("signal number %2d received\n", sig);
      (void)fflush(stdout);
   }

   if ((sig == SIGILL) || (sig == SIGBUS) || (sig == SIGSEGV))
   {
      error("got a fatal signal to abort.. signal = %d\n\n", sig);

      if (done == 1) return;
      else longjmp(doquit, ERROR);
   }

   else if ((sig == SIGINT) || (sig == SIGTERM) || (sig == SIGQUIT))
   {
      if (done == 1) return;
      else longjmp(doquit, ABORT);
   }

   else if (sig == SIGPIPE)
   {
      connected = 0;

      error("the server dropped the connection..\n\n");

      if (done == 1) return;
      else longjmp(sigdropconn, 1);
   }

   else if (sig == SIGUSR1) running = 1;

   else if (sig == SIGHUP)
   {
      config(); /* re-read config file */
      (void)signal(SIGHUP, sighandler);
   }

   else 
   {
      char *error = "Error: that signal is not being handled\n";
      (void)write(STDERR, error, strlen(error));
   }

   errno = oerrno; /* restore old errno */
}


/* --------------------- */


/* called when we've timed out after restarting at top of server list */
RETSIGTYPE restart(int sig)
{
    error("unable to reconnect to a streaming server..\n"
          "getting a new server list\n\n");

   if (done == 1) return;
   else longjmp(infoconn, 1);
}
/* --------------------- */
      

/* timed out checking for an error */
RETSIGTYPE errTimeout(int sig)
{
   gotAlrm = 1;
   return;
}


/* --------------------- */


/* called when we timeout waiting for Sub-ID */
void subIDTimeout(int sig) 
{
   error("timed out while waiting for Sub-ID.. aborting\n\n");

   if (done == 1) return;
   else longjmp(doquit, ERROR);
}


/* --------------------- */
 

/* timeouit waiting for server list */
RETSIGTYPE listTimeout(int sig)
{
   error("timed out while waiting for server list.. aborting\n\n");

   if (done == 1) return;
   else longjmp(doquit, ERROR);
}


/* --------------------- */


/* called when we time out waiting for server to send us */
/* the current client and server versions                */

RETSIGTYPE verTimeout(int sig)
{
   error("timed out waiting for server/client version.. aborting\n\n");

   if (done == 1) return;
   else longjmp(doquit, ERROR);
}


/* --------------------- */


/* called when we timeout sending or receiving "OKAY" */
RETSIGTYPE okayTimeout(int sig)
{
   error("timed out waiting for or sending OKAY\n\n");
   gotAlrm = 1;
}


/* -------------------------- */


/* called when child OK's us to run */
RETSIGTYPE startUp(int sig)
{
   if (debugging == 1)
   {
      char *error = "(in parent) got SIGUSR2 from child (free to continue)\n";
      (void)write(STDOUT, error, strlen(error));
   }

   /* FIX - make reentrant by using sigaction() instead */
   /*     - or sigaddset, sigemptyset, etc.             */

   (void)signal(SIGUSR2, startUp);

   running = 1;
   return;
}


/* --------------------- */


/* called when we get new data.. according to parent */
RETSIGTYPE gotNewData(int sig)
{
   if (debugging == 1)
   {
      char *error= "(in child) got SIGUSR1 from parent (new data available)\n";
      (void)write(STDOUT, error, strlen(error));
   }

   /* FIX - make reentrant by using sigaction() instead */
   /*     - or sigaddset, sigemptyset, etc.             */

   (void)signal(SIGUSR1, gotNewData);
   newData = 1;

   return;
}


/* --------------------- */


/* signal handler when sigpipe from info server is received */
RETSIGTYPE dropinfoconn(int sig)
{
   /* FIX - make reentrant by using sigaction() instead */
   /*     - or sigaddset, sigemptyset, etc.             */

   error("connection with info server dropped..\n"
         "reconnecting to new one\n\n");

#  ifdef BEEP   
   if (debugging == 1) (void)putchar('\a');
#  endif

   connected = 0;

   if (done == 1) return;
   else longjmp(infoconn, 1);
}


/* ---------------------- */


/* called when SIGPIPE (connection dropped) is received */
RETSIGTYPE dropstreamconn(int stat)
{
   int res; /* used for checking some results */

   res = setjmp(sigdropconn);
   if (res == ERROR)
   {
      error("error with setjmp(): %s\n\n", strerror(errno));
      quit(ERROR);
   }

   if (stat == INIT) return; /* they just came to init it */

   connected = 0;

#  ifdef BEEP   
   if (debugging == 1) (void)putchar('\a');
#  endif

   error("server #%d (%s, port %d) dropped connection...\n\n",
         curServ, servList[curServ].name, servList[curServ].port);
 
   if (done == 1) return;
   else longjmp(dropconn, 1);
}
