/* **********************************************************************
 * *                                                                    *
 * *                                                                    *
 * *                                                                    *
 * **********************************************************************
 * File: utils/custom/iris_iwhu_interface.c
 *
 *            COPYRIGHT (c) 1998, 1999, 2000, 2001, 2002  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */

/*****
   This program performs the following functions:
   1) Receives product notification socket messages from an IRIS server
   2) When notified in (1), reads in a product and collects information from it 
   3) Reads from the antenna driver to collect some information from the RCP
   4) Sends a TSM and AWWM file to the IWHU server based on info collected in (2) and (3)
*****/

#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/socket.h>
#include <netdb.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <unistd.h>

#include "sigtypes.h"
#include "headers.h"
#include "product.h"
#include "setup.h"

#define DEV_OK 1

void Lprintf(const char *log_str);
static void sighup_handler (int signal_a);
static void sigio_handler (int signal_a);
int connected_iris_mode = 0;
int iris_mode_s;
int logging = 0;
char log_str[200];
struct sigaction action;
FILE *log_file;

struct Runway
{
  char AppNum[4];
  char AppArena[4];
  char AppAlert[4];
  char AppLevel[4];
  char DepNum[4];
  char DepArena[4];
  char DepAlert[4];
  char DepLevel[4];
  int  AppLossGain;
  int  DepLossGain;
};
  
struct AWWM
{
  char Timestamp[16];
  struct Runway Runway[5];
};

struct TSM
{
  char Timestamp[16];
  int Channel1Status;
  int Channel2Status;
  int OnlineChannel;
  int ScanMode;
  int RPG1Status;
  int RPG2Status;
  int RDA1Status;
  int RDA2Status;
  int RSP1Status;
  int RSP2Status;
  int XMT1Status;
  int XMT2Status;
  int RCP1Status;
  int RCP2Status;
  int AntennaStatus;
  int WindAlert;
  int StormAlert;
};


int main (int argc, char ** argv)
{
  short iris_mode_port_num;
  int iris_pending = 0;
  char iris_mode_name[200], iris_mode_port[20], report_mode[100];
  int i, j, k, m, n, p, ms_count, answer, alen;
  int iris_ms[5], iris_ss, iflag, count, offset;
  int tmp_status, send_awwm, send_tsm, send_mode, iknots;
  int fault_index0, fault_index1, fault_array[2][3], fault_num;
  int awwm_count, tsm_count;
  int tmp_status1, tmp_status2;
  int scanmode_a, scanmode_b, ifamily, iaddrsize, iPid;
  float fknots;
  struct timeval tv;
  fd_set afds;
  char mon_str[4], day_str[4], hou_str[4], min_str[4], sec_str[4];
  char iris_port[20], iris_dir[100], buf[10000];
  char iwhu_name[200], tsm_dir[200], awwm_dir[200];
  char prod_file_name[5000], del_string[5000], buf_str[100][100];
  char tmp_str[5000], channel_str[20], status_sitename[20];
  char file1_str[100], file2_str[100];
  char PriAppDir[5][4], SecAppDir[5][4], PriDepDir[5][4], SecDepDir[5][4]; 
  struct product_hdr prod_hdr;
  struct sockaddr fsin;
  struct sockaddr_in sin, servaddr_in;
  struct hostent *hostptr;
  struct in_addr *paddress;
  struct sockaddr *pservaddr;
  struct AWWM awwm;
  struct TSM tsm;
  struct tdwr_results tdwr_results[16];
  struct status_results status_results;
  struct warning_results warning_results;
  struct protect_setup protect_setup;
  time_t now_time, tsm_time, awwm_time, mode_time;
  time_t rpg1_time, rpg2_time, rda1_time, rda2_time;
  FILE *out_file, *config_file, *prod_file;

  action.sa_handler = sighup_handler;
  sigemptyset( &action.sa_mask );
  action.sa_flags = SA_RESTART;
  answer = sigaction( SIGHUP, &action, NULL );

  /*****
    Process the configuration file
    The config file is organized as follows and must be in this order:
    LOG     <0 or 1>
    MODE    <iris_mode_server_NAME> <iris_mode_server_PORT>  (NAME and PORT where we send mode changes)
    NOTIFY  <iris_notify_PORT> <iris_notify_DIR>  (we listen to PORT for notification of inbound files in DIR)
    IWHU    <server_1_NAME> <server_1_DIR>  (NAME and DIR of IWHU server we write to)
    CHANNEL <A or B>
    XMT     <list of BITE faults that are critical transmitter faults>
    ANT     <list of BITE faults that are critical antenna faults>
  *****/
  if (argc != 2)
  {
    printf("usage: iris_iwhu_interface <config file name>\n");
    exit(0);
  }

  if ((config_file = fopen(argv[1], "r")) == NULL)
  {
    sprintf(log_str, "Can not open config file: %s\n", argv[1]);
    printf(log_str);
    exit(-1);
  }

  answer = fscanf(config_file, "%s%s", tmp_str, log_str);
  if (answer <= 0 || strcmp(tmp_str, "LOG"))
  {
    printf("No valid LOG line!\n");
    exit(-2);
  }
  if (log_str[0] == '1') 
  {
    if ((log_file = fopen("/tmp/iris_iwhu_interface.dat", "w")) == NULL)
    {
      printf("Can not open log file: /tmp/iris_iwhu_interface.dat!\n");
      exit(-2);
    }
    else 
    {
      logging = 1;
      printf("Logging to file: /tmp/iris_iwhu_interface.dat.\n");
    }
  }

  answer = fscanf(config_file, "%s%s%s", tmp_str, iris_mode_name, iris_mode_port);
  if (answer <= 0 || strcmp(tmp_str, "MODE"))
  {
    Lprintf("No valid IRIS mode change server / port listed.\n");
    exit(-2);
  }
  sprintf(log_str, "Using IRIS mode change server and port: %s %s\n", iris_mode_name, iris_mode_port);
  Lprintf(log_str);

  answer = fscanf(config_file, "%s%s%s", tmp_str, iris_port, iris_dir);
  if (answer <= 0 || strcmp(tmp_str, "NOTIFY"))
  {
    printf("No valid IRIS product notification port or directory!\n");
    exit(-2);
  }
  sprintf(log_str, "Using IRIS product notification port %s with directory %s.\n", iris_port, iris_dir);
  Lprintf(log_str);
  sprintf(del_string, "rm -rf %s*", iris_dir);
  system(del_string); 

  answer = fscanf(config_file, "%s%s%s%s", tmp_str, iwhu_name, tsm_dir, awwm_dir);
  if (answer <= 0 || strcmp(tmp_str, "IWHU"))
  {
    Lprintf("No valid IWHU server / dir listed.\n");
    exit(-2);
  }
  sprintf(log_str, "Using IWHU server and dirs: %s %s %s \n", iwhu_name, tsm_dir, awwm_dir);
  Lprintf(log_str);

  answer = fscanf(config_file, "%s%s", tmp_str, channel_str);
  if (answer <= 0 || strcmp(tmp_str, "CHANNEL"))
  {
    printf("No valid CHANNEL line!\n");
    exit(-2);
  }
  if (channel_str[0] != 'A' && channel_str[0] != 'B') 
  {
    printf("CHANNEL line not valid - specify A or B.\n");
    exit(-2);
  }

  answer = fscanf(config_file, "%s", tmp_str);
  if (answer <= 0 || strncmp(tmp_str, "XMT", 3))
  {
    printf("No valid XMT line!\n");
    exit(-2);
  }
  fault_index0 = fault_index1 = 0;
  for (fault_index0=0; fault_index0<2; fault_index0++)
  {
    for (fault_index1=0; fault_index1<3; fault_index1++)
    {
      fault_array[fault_index0][fault_index1] = 0;
    }
  }

  answer = fscanf(config_file, "%s", tmp_str);
  fault_index0 = fault_index1 = 0;
  while(answer > 0)
  {
    if (strncmp(tmp_str, "ANT", 3) == 0) fault_index0 = 1;
    else
    {
      fault_num = atoi(tmp_str) - 1;
      fault_index1 = fault_num / 32;
      fault_array[fault_index0][fault_index1] = 
            fault_array[fault_index0][fault_index1] + (1 << (fault_num % 32));
    }
    answer = fscanf(config_file, "%s", tmp_str);
  }
  fclose(config_file);

  /* Initialize a bunch of stuff */
  memcpy(awwm.Runway[1].AppNum, "15LA", 4);
  memcpy(awwm.Runway[1].DepNum, "15LD", 4);
  memcpy(PriAppDir[1], "15LA", 4);
  memcpy(PriDepDir[1], "15LD", 4);
  memcpy(SecAppDir[1], "33RA", 4);
  memcpy(SecDepDir[1], "33RD", 4);
  memcpy(awwm.Runway[2].AppNum, "15RA", 4);
  memcpy(awwm.Runway[2].DepNum, "15RD", 4);
  memcpy(PriAppDir[2], "15RA", 4);
  memcpy(PriDepDir[2], "15RD", 4);
  memcpy(SecAppDir[2], "33LA", 4);
  memcpy(SecDepDir[2], "33LD", 4);
  memcpy(awwm.Runway[3].AppNum, "16LA", 4);
  memcpy(awwm.Runway[3].DepNum, "16LD", 4);
  memcpy(PriAppDir[3], "16LA", 4);
  memcpy(PriDepDir[3], "16LD", 4);
  memcpy(SecAppDir[3], "34RA", 4);
  memcpy(SecDepDir[3], "34RD", 4);
  memcpy(awwm.Runway[4].AppNum, "16RA", 4);
  memcpy(awwm.Runway[4].DepNum, "16RD", 4);
  memcpy(PriAppDir[4], "16RA", 4);
  memcpy(PriDepDir[4], "16RD", 4);
  memcpy(SecAppDir[4], "34LA", 4);
  memcpy(SecDepDir[4], "34LD", 4);

  for (i=1; i<5; i++)
  {
    memcpy(awwm.Runway[i].AppArena, "    ", 4); 
    memcpy(awwm.Runway[i].AppAlert, "    ", 4); 
    memcpy(awwm.Runway[i].AppLevel, "    ", 4); 
    memcpy(awwm.Runway[i].DepArena, "    ", 4); 
    memcpy(awwm.Runway[i].DepAlert, "    ", 4); 
    memcpy(awwm.Runway[i].DepLevel, "    ", 4); 
  }

  tsm.Channel1Status = 0;
  tsm.Channel2Status = 0;
  tsm.OnlineChannel = 0;
  tsm.ScanMode = 0;
  tsm.RPG1Status = 1;
  tsm.RPG2Status = 1;
  tsm.RDA1Status = 1;
  tsm.RDA2Status = 1;
  tsm.RSP1Status = 1;
  tsm.RSP2Status = 1;
  tsm.XMT1Status = 1;
  tsm.XMT2Status = 1;
  tsm.RCP1Status = 1;
  tsm.RCP2Status = 1;
  tsm.AntennaStatus = 1;
  tsm.WindAlert = 0;
  tsm.StormAlert = 0;

  send_mode = 1;
  awwm_count = tsm_count = 0;
  tsm_time = 0;
  awwm_time = 0;
  mode_time = 0;
  rpg1_time = rpg2_time = rda1_time = rda2_time = time(NULL);

  for (i=0; i<5; i++)
  {
    iris_ms[i] = 0;
  }

  /*****
    Establish a socket to listen to so an IRIS servers can send us notification
    messages about the transfer of products.
  *****/
  iris_ss = 0;
  memset ((char *) &sin, 0, sizeof (sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(atoi(iris_port));
  while(iris_ss <= 0)
  {
    iris_ss = socket (PF_INET, SOCK_STREAM, 0);
    if (iris_ss < 0) 
    {
      sprintf(log_str, "Socket call for IRIS product notify failed with errno: %d\n", errno);
      Lprintf(log_str);
    }
    else 
    {
      if (bind (iris_ss, (struct sockaddr *) &sin, sizeof (sin)) < 0) 
      {
        sprintf(log_str, "Bind call for IRIS product notify failed with errno: %d\n", errno);
        Lprintf(log_str);
	iris_ss = -1;
        close(iris_ss);
      }
      else
      {
        if (listen (iris_ss, 5) < 0) 
        {
          sprintf(log_str, "Listen call for IRIS product notify failed with errno: %d\n", errno);
          Lprintf(log_str);
	  iris_ss = -1;
          close(iris_ss);
        }
        else
        {
          Lprintf("Socket open for listening for IRIS product notifications\n");
          break;
        }
      }
    }
    Lprintf("Will try again in 5 seconds.\n");
    sleep(5);
  }


  /*****
    The main loop of the program.  The program will cycle once per second.
    In this cycle, if will do the following in the following order:
    1) If not connected via a socket to an IRIS server that we send mode
       change messages to, try to establish this connection.
    2) If connection to mode server is pending, see if it is ready. 
    3) See if any connections are pending on the IRIS server socket that we
       listen to for product notifications.  If so, then open a socket
       for this server.
    4) See if any product notifications are pending and if so, process them.
    5) Check to see what is the online channel, and send mode change command if necessary.
    6) If it is time to send a TSM or AWWM message to IWHU, do so.
  *****/
  while (1) 
  {
    /*****
      1) If not connected via a socket to an IRIS server that we send mode
         change messages to, try to establish this connection.
    *****/
    if (!connected_iris_mode && !iris_pending)
    {
      ifamily = AF_INET;
      hostptr = gethostbyname((char *)(&iris_mode_name[0]));
      if (hostptr != NULL)
      {
        memset( &servaddr_in, 0, sizeof(servaddr_in));
        servaddr_in.sin_family = ifamily;
        paddress = (struct in_addr *)hostptr->h_addr_list[0];
        servaddr_in.sin_addr = *paddress;
	iris_mode_port_num = atoi(iris_mode_port);
        servaddr_in.sin_port = htons(iris_mode_port_num);
        pservaddr = (struct sockaddr *)&servaddr_in;
        iaddrsize = sizeof( servaddr_in );

        iris_mode_s = socket(ifamily,SOCK_STREAM,0);
        if (iris_mode_s > 0)
        {
          /* Set up so that i/o is nonblocking */
          iflag = 1;
          answer = ioctl( iris_mode_s, FIONBIO, &iflag );

          answer = connect(iris_mode_s, pservaddr, iaddrsize);
          if (answer >= 0)
          {
            /* Set up a signal handler for the SIGIO signal */
            action.sa_handler = sigio_handler;
            sigemptyset( &action.sa_mask );
            action.sa_flags = SA_RESTART;
            answer = sigaction( SIGIO, &action, NULL );
	    iPid = getpid();
	    answer = fcntl( iris_mode_s, F_SETOWN, iPid );
            iflag = 1;
            answer = ioctl( iris_mode_s, FIOASYNC, &iflag );
            iflag = 1;
            answer = ioctl( iris_mode_s, FIONBIO, &iflag );
	    connected_iris_mode = 1;
	    sprintf(log_str, "Connected successfully to IRIS mode change server %s port %s.\n", 
                     iris_mode_name, iris_mode_port);
            Lprintf(log_str);
          }
          else /* else, not connected, but ... */
          {
            if (errno == EINPROGRESS)
            {
              sprintf(log_str, "Connection pending to IRIS mode change server %s port %s.\n",
                       iris_mode_name, iris_mode_port);
              Lprintf(log_str);
              iris_pending = 1;
            }
            else
            {
              sprintf(log_str, "Connection failed to IRIS mode change server %s with errno = %d.\n",
                      iris_mode_name, errno);
              Lprintf(log_str);
              iris_pending = 0;
              close(iris_mode_s);
              iris_mode_s = 0;
            }   
          } /* endif connect */
        } /* endif socket open */
        else
        {
  	  Lprintf("Socket open failed to IRIS mode change server.\n");
        }
      }
      else
      {
	sprintf(log_str, "Error getting hostname: %s\n", iris_mode_name);
	Lprintf(log_str);
      } /* endif gethostname */
    } /* endif (!connected_iris_mode && !iris_pending) */


    /*****
      2) if connection to mode server is pending, see if it is ready. 
    *****/
    if (iris_pending)
    {
      FD_ZERO(&afds);
      FD_SET(iris_mode_s, &afds);
      tv.tv_sec = 0;
      tv.tv_usec = 0;
      answer = select(32, NULL, &afds, NULL, &tv);
      switch (answer)
      {
        case -1: /* error */	
          sprintf(log_str, "select() for IRIS notification or AGL returned error (%d)\n", errno);
  	  Lprintf(log_str);
        break;
        default: /* got something */
          if (FD_ISSET(iris_mode_s, &afds))
          {
            hostptr = gethostbyname((char *)(&iris_mode_name[0]));
            if (hostptr != NULL)
            {
              memset( &servaddr_in, 0, sizeof(servaddr_in));
              servaddr_in.sin_family = ifamily;
              paddress = (struct in_addr *)hostptr->h_addr_list[0];
              servaddr_in.sin_addr = *paddress;
	      iris_mode_port_num = atoi(iris_mode_port);
              servaddr_in.sin_port = htons(iris_mode_port_num);
              pservaddr = (struct sockaddr *)&servaddr_in;
              iaddrsize = sizeof( servaddr_in );
              answer = connect(iris_mode_s, pservaddr, iaddrsize);
              if ((answer >= 0) || (answer < 0 && errno == EISCONN))
              {
                /* Set up a signal handler for the SIGIO signal */
                action.sa_handler = sigio_handler;
                sigemptyset( &action.sa_mask );
                action.sa_flags = SA_RESTART;
                answer = sigaction( SIGIO, &action, NULL );
                /* Set up so that i/o causes the SIGIO signal */
	        iPid = getpid();
		answer = fcntl( iris_mode_s, F_SETOWN, iPid );
                iflag = 1;
                answer = ioctl( iris_mode_s, FIOASYNC, &iflag );
                iflag = 1;
                answer = ioctl( iris_mode_s, FIONBIO, &iflag );
	        connected_iris_mode = 1;
                iris_pending = 0;
	        sprintf(log_str, "Connected successfully to IRIS mode change server %s.\n", iris_mode_name);
                Lprintf(log_str);
              }
              else
              {
                sprintf(log_str, "Connection failed to IRIS mode change server %s with errno = %d\n", iris_mode_name, errno);
                Lprintf(log_str);
                iris_pending = 0;
                close(iris_mode_s);
                iris_mode_s = 0;
              }
            }
            else
            {    
	      sprintf(log_str, "Error getting hostname: %s\n", iris_mode_name);
  	      Lprintf(log_str);
              iris_pending = 0;
              close(iris_mode_s);
              iris_mode_s = 0;
            }
          }
          else
          {
            iris_pending++;
            if (iris_pending == 30)
            {
              Lprintf ("IRIS mode change connection not established.  Will try again fresh.\n");
              iris_pending = 0;
              close(iris_mode_s);
              iris_mode_s = 0;
            }
          }
        break;
      } /* end switch */
    } /* endif iris_pending */


    /*****
      3) See if any connections are pending on the IRIS listen socket that we
         listen connections from IRIS servers.  If so, then accept this
         connection.
    *****/
    FD_ZERO(&afds);
    FD_SET(iris_ss, &afds); 
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    answer = select(32, &afds, NULL, NULL, &tv);
    while (answer > 0)
    {
      if (FD_ISSET(iris_ss, &afds))
      {
        ms_count = -1;
        for (i=0; i<5; i++)
        {
          if (iris_ms[i] == 0)
          {
            ms_count = i;
            break;
          }
        } 
        if (ms_count == -1)
        {
          Lprintf("Error: Socket connection pending, but no more accepts available.\n");
          break;
        }

        iris_ms[ms_count] = accept(iris_ss, &fsin, (void *)&alen);
        if (iris_ms[ms_count] <= 0)
        {
          sprintf( log_str,
                "Error errno = %d in accept() for IRIS notification server.\n", errno);
	  Lprintf(log_str);
          iris_ms[ms_count] = 0;
        }
        else
	{
          iflag = 1;
          answer = ioctl( iris_ms[ms_count], FIONBIO, &iflag );
	  sprintf(log_str, "Connection established from socket %d .\n", ms_count);
          Lprintf(log_str);
	}
      }
      FD_ZERO(&afds);
      FD_SET(iris_ss, &afds); 
      tv.tv_sec = 0;
      tv.tv_usec = 0;
      answer = select(32, &afds, NULL, NULL, &tv);
    } /* end while accepts available */


    /*****
      4) See if there are any messages pending on the notification sockets,
         and if so, then process them.
    *****/
    FD_ZERO(&afds);
    for (i=0; i<5; i++)
    {
      if (iris_ms[i] > 0) FD_SET(iris_ms[i], &afds);
    }
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    answer = select(32, &afds, NULL, NULL, &tv);
    while (answer > 0)
    {
      /* For each of the upto 5 sockets that could be open ... */
      for (j=0; j<5; j++)
      {
        /* If there is a message to this socket ... */
        if (FD_ISSET(iris_ms[j], &afds))
        {
          offset = 0;
          /* Read from the socket until we get the full message into buf */
          do {
            n = recv(iris_ms[j], &buf[offset], 1024, 0);
            offset += n;
	    if (offset >= 3000)
	    {
	      Lprintf("Socket stream too long - truncating\n");
	      break;
            }
          } while (n > 0);
          buf[offset] = '\0' ;
          sprintf(log_str, "Read %d bytes from IRIS notification socket.\n", offset);
	  Lprintf(log_str);
          /* If this was not a null read (a null read means close which is handled below), then ... */
          if (offset > 0)
          {
            /* This do loop will parse the socket string into blocks where each block
               is a file notification. */
            count = n = 0;
            do {
	      if (strlen(&buf[n]) > 99) buf[n+99] = 0;
              strcpy(buf_str[count], &buf[n]);
              n = n + strlen(&buf[n]) + 1;
	      count++;
	      if (count >= 99)
	      {
		break;
		Lprintf("Too many files in this socket stream.  Truncating\n");
	      }	 
            } while(n < offset);

            /* For each message on the socket ... */
            for (i=0; i<count; i++)
	    {
              /* If this is a product notification message ... */
              if (strncmp(buf_str[i], "FILE", 4) == 0)
              {
                sprintf(prod_file_name, "%s%s", iris_dir, &buf_str[i][5]);
                if( (prod_file = fopen(prod_file_name, "r+b")) != 0 ) 
                {
                  answer = fread(&prod_hdr, 1, PRODUCT_HDR_SIZE, prod_file);
                  switch (prod_hdr.pcf.iptype) 
                  {
                    case PROD_TDWR:
                      sprintf(log_str, "Received TDWR product %s from IRIS.\n", prod_file_name);
                      Lprintf(log_str);
                      
                      /* Read the tdwr_results structures into an array of them ... */
                      k = 0;
                      answer = fread(&protect_setup, 1, PROTECT_SETUP_SIZE, prod_file);
                      for (k=0; k<prod_hdr.end.iresults_count; k++)
	              {
                        answer = fread(&tdwr_results[k], 1, TDWR_RESULTS_SIZE, prod_file);
		      } 

                      /* For each of the tdwr_results structures read ... */
                      tmp_status = tsm.WindAlert;
                      tsm.WindAlert = 0;
                      for (m=0; m<prod_hdr.end.iresults_count; m++)
                      {
                        /* Because on of the bit fields in the TSM asks if a windshear alert
                           is present, here we check if an alert is present and there was
                           none before, or if now there is none present and there was one
                           before.  If this is true, then flag the sending of the TSM */
                        if (tdwr_results[m].iLossGain != 0)
                        {
                          tsm.WindAlert = 1;
                          break;
                        }
                      }
                      if (tmp_status != tsm.WindAlert) send_tsm = 1;

                      /* For each of the tdwr_results structures read ... */
                      for (m=0; m<prod_hdr.end.iresults_count; m++)
                      {
                        /* Check if this tdwr_results structure matches either the Arrival or
                           Departure corridor (in either direction also) for this runway [p].
                           If it does match, then check to see if any of the fields have changed.
                           If they have, then update the awwm structure and set the flag to
                           send the awwm message immeadiately */
                        for (p=1; p<=4; p++)
                        {
                          if ( (strncmp(PriAppDir[p], tdwr_results[m].sCorridor, 4) == 0) ||
                               (strncmp(SecAppDir[p], tdwr_results[m].sCorridor, 4) == 0) )
                          {
                            if (strncmp(awwm.Runway[p].AppNum, tdwr_results[m].sCorridor, 4) != 0)
                            {
                              memcpy(awwm.Runway[p].AppNum, tdwr_results[m].sCorridor, 4);
                              send_awwm = 1;
                            }
                            if (strlen(tdwr_results[m].sArena) == 0) 
                                  memcpy(tdwr_results[m].sArena, "   ", 3);
                            if (strncmp(awwm.Runway[p].AppArena, tdwr_results[m].sArena, 3) != 0)
                            {
                              memcpy(awwm.Runway[p].AppArena, "    ", 4);
                              memcpy(awwm.Runway[p].AppArena, tdwr_results[m].sArena, 3);
                              send_awwm = 1;
                            }
                            if (strlen(tdwr_results[m].sAlertType) == 0) 
                                memcpy(tdwr_results[m].sAlertType, "   ", 3);
                            if (strncmp(awwm.Runway[p].AppAlert, tdwr_results[m].sAlertType, 3) != 0)
                            {
                              memcpy(awwm.Runway[p].AppAlert, "    ", 4);
                              memcpy(awwm.Runway[p].AppAlert, tdwr_results[m].sAlertType, 3);
                              send_awwm = 1;
                            }
                            if (awwm.Runway[p].AppLossGain != tdwr_results[m].iLossGain)
                            {
                              awwm.Runway[p].AppLossGain = tdwr_results[m].iLossGain;
                              if (tdwr_results[m].iLossGain == 0)
                              {
                                memcpy(awwm.Runway[p].AppLevel, "    ", 4);
                              }
                              else
                              {
                                if (tdwr_results[m].iLossGain < 0) 
                                   memcpy(&awwm.Runway[p].AppLevel[2], "K-", 2);
                                else
                                   memcpy(&awwm.Runway[p].AppLevel[2], "K+", 2);
                                fknots = fabs(((float)tdwr_results[m].iLossGain * 0.001) / MPS_PER_KNOT);
                                fknots = (fknots + 5.0) / 5.0;
                                iknots = (int)fknots;
                                iknots = iknots * 5;
                                if (iknots > 99) iknots = 99;
                                sprintf(tmp_str, "00%d", iknots);
                                memcpy(awwm.Runway[p].AppLevel, &tmp_str[strlen(tmp_str)-2], 2);
                              }
                              send_awwm = 1;
                            }
                            break;
                          }
                          if ( (strncmp(PriDepDir[p], tdwr_results[m].sCorridor, 4) == 0) ||
                               (strncmp(SecDepDir[p], tdwr_results[m].sCorridor, 4) == 0) )
                          {
                            if (strncmp(awwm.Runway[p].DepNum, tdwr_results[m].sCorridor, 4) != 0)
                            {
                              memcpy(awwm.Runway[p].DepNum, tdwr_results[m].sCorridor, 4);
                              send_awwm = 1;
                            }
                            if (strlen(tdwr_results[m].sArena) == 0) 
                                  memcpy(tdwr_results[m].sArena, "   ", 3);
                            if (strncmp(awwm.Runway[p].DepArena, tdwr_results[m].sArena, 3) != 0)
                            {
                              memcpy(awwm.Runway[p].DepArena, "    ", 4);
                              memcpy(awwm.Runway[p].DepArena, tdwr_results[m].sArena, 3);
                              send_awwm = 1;
                            }
                            if (strlen(tdwr_results[m].sAlertType) == 0) 
                                  memcpy(tdwr_results[m].sAlertType, "   ", 3);
                            if (strncmp(awwm.Runway[p].DepAlert, tdwr_results[m].sAlertType, 3) != 0)
                            {
                              memcpy(awwm.Runway[p].DepAlert, "    ", 4);
                              memcpy(awwm.Runway[p].DepAlert, tdwr_results[m].sAlertType, 3);
                              send_awwm = 1;
                            }
                            if (awwm.Runway[p].DepLossGain != tdwr_results[m].iLossGain)
                            {
                              awwm.Runway[p].DepLossGain = tdwr_results[m].iLossGain;
                              if (tdwr_results[m].iLossGain == 0)
                              {
                                memcpy(awwm.Runway[p].DepLevel, "    ", 4);
                              }
                              else
                              {
                                if (tdwr_results[m].iLossGain < 0) 
                                   memcpy(&awwm.Runway[p].DepLevel[2], "K-", 2);
                                else
                                   memcpy(&awwm.Runway[p].DepLevel[2], "K+", 2);
                                fknots = fabs(((float)tdwr_results[m].iLossGain * 0.001) / MPS_PER_KNOT);
                                fknots = (fknots + 5.0) / 5.0;
                                iknots = (int)fknots;
                                iknots = iknots * 5;
                                if (iknots > 99) iknots = 99;
                                sprintf(tmp_str, "00%d", iknots);
                                memcpy(awwm.Runway[p].DepLevel, &tmp_str[strlen(tmp_str)-2], 2);
                              }
                              send_awwm = 1;
                            }
                            break;
                          }
                        }
                      } 
                    break;

                    case PROD_WARN:
                      sprintf(log_str, "Received WARN product %s from IRIS.\n", prod_file_name);
                      Lprintf(log_str);
  
                      tmp_status = tsm.StormAlert;
                      tsm.StormAlert = 0;
                      answer = fread(&protect_setup, 1, PROTECT_SETUP_SIZE, prod_file);
                      answer = fread(&warning_results, 1, WARNING_RESULTS_SIZE, prod_file);
                      while (answer > 0)
                      {
                        if (prod_hdr.pcf.psi.warn.iprotect_mask & 
                                      warning_results.iprotect_mask)
                        {
                          tsm.StormAlert = 1;
                          break;
                        }
                        answer = fread(&warning_results, 1, WARNING_RESULTS_SIZE, prod_file);
                      }
                      if (tmp_status != tsm.StormAlert) send_tsm = 1;
                    break;

                    case PROD_STATUS:
                      fread(&status_results, 1, sizeof(struct status_results), prod_file);
                      memcpy(status_sitename, prod_hdr.end.sIngHardwareName, 8);
                      status_sitename[8] = (char)NULL;
                      if (strcmp(status_sitename, "IIA_RPGA") == 0)
                      {
                        rpg1_time = time(NULL);
                        tmp_status = tsm.RPG1Status;
                        if (status_results.misc.iflags & STAT_FLG_CRITICAL) tsm.RPG1Status = 0;
                        else tsm.RPG1Status = 1;
                        if (tmp_status != tsm.RPG1Status) send_tsm = 1;
                      }

                      if (strcmp (status_sitename, "IIA_RPGB") == 0)
                      {
                        rpg2_time = time(NULL);
                        tmp_status = tsm.RPG2Status;
                        if (status_results.misc.iflags & STAT_FLG_CRITICAL) tsm.RPG2Status = 0;
                        else tsm.RPG2Status = 1;
                        if (tmp_status != tsm.RPG2Status) send_tsm = 1;
                      }

                      if (strcmp (status_sitename, "IIA_RDAA") == 0)
                      {
                        rda1_time = time(NULL);
                        tmp_status = tsm.RDA1Status;
                        if (status_results.misc.iflags & STAT_FLG_CRITICAL) 
                        {
                          tsm.RDA1Status = 0;
                          tsm.Channel1Status = 2;
                        }
                        else 
                        {
                          tsm.RDA1Status = 1;
                          tsm.Channel1Status = 1;
                        }
                        if (tmp_status != tsm.RDA1Status) send_tsm = 1;
    
			tmp_status = scanmode_a;
		        scanmode_a = 0;
                        if (strncmp(status_results.misc.srst_name, "MON", 3) == 0) scanmode_a = 1;
                        if (strncmp(status_results.misc.srst_name, "HAZ", 3) == 0) scanmode_a = 2;
			if (tmp_status != scanmode_a) send_mode = 1;

                        tmp_status = tsm.RSP1Status;
                        if (status_results.device.dsp.istatus == DEV_OK) tsm.RSP1Status = 1;
                        else tsm.RSP1Status = 0;
                        if (tmp_status != tsm.RSP1Status) send_tsm = 1;

                        tmp_status = tsm.RCP1Status;
                        if (status_results.device.antenna.istatus == DEV_OK) tsm.RCP1Status = 1;
                        else tsm.RCP1Status = 0;
                        if (tmp_status != tsm.RCP1Status) send_tsm = 1;

                        tmp_status = tsm.XMT1Status; 
                        tsm.XMT1Status = 1;
                        for (p=0; p<3; p++)
                        {
                          if (status_results.antenna.iBiteFaults[p] & fault_array[0][p])
                          {
                            tsm.XMT1Status = 0;
                            break;
                          }
                        }
                        if (tmp_status != tsm.XMT1Status) send_tsm = 1;
                     
                        if (channel_str[0] == 'A')
                        {
                          tmp_status = tsm.AntennaStatus; 
                          tsm.AntennaStatus = 1;
                          for (p=0; p<3; p++)
                          {
                            if (status_results.antenna.iBiteFaults[p] & fault_array[1][p])
                            {
                              tsm.AntennaStatus = 0;
                              break;
                            }
                          }
                        }
                        if (tmp_status != tsm.AntennaStatus) send_tsm = 1;
                      } 

                      if (strcmp (status_sitename, "IIA_RDAB") == 0)
                      { 
                        rda2_time = time(NULL);
                        tmp_status = tsm.RDA2Status;
                        if (status_results.misc.iflags & STAT_FLG_CRITICAL)
                        {
                          tsm.RDA2Status = 0;
                          tsm.Channel2Status = 2;
                        }
                        else
                        {
                          tsm.RDA2Status = 1;
                          tsm.Channel2Status = 1;
                        }
                        if (tmp_status != tsm.RDA2Status) send_tsm = 1;
  
			tmp_status = scanmode_b;
	        	scanmode_b = 0;
                        if (strncmp(status_results.misc.srst_name, "MON", 3) == 0) scanmode_b = 1;
                        if (strncmp(status_results.misc.srst_name, "HAZ", 3) == 0) scanmode_b = 2;
			if (tmp_status != scanmode_b) send_mode = 1;

                        tmp_status = tsm.RSP2Status;
                        if (status_results.device.dsp.istatus == DEV_OK) tsm.RSP2Status = 1;
                        else tsm.RSP2Status = 0;
                        if (tmp_status != tsm.RSP2Status) send_tsm = 1;
  
                        tmp_status = tsm.RCP2Status;
                        if (status_results.device.antenna.istatus == DEV_OK) tsm.RCP2Status = 1;
                        else tsm.RCP2Status = 0;
                        if (tmp_status != tsm.RCP2Status) send_tsm = 1;
  
                        tmp_status = tsm.XMT2Status; 
                        tsm.XMT2Status = 1;
                        for (p=0; p<3; p++)
                        {
                          if (status_results.antenna.iBiteFaults[p] & fault_array[0][p])
                          {
                            tsm.XMT2Status = 0;
                            break;
                          }
                        }
                        if (tmp_status != tsm.XMT2Status) send_tsm = 1;
                     
                        if (channel_str[0] == 'B')
                        {
                          tmp_status = tsm.AntennaStatus; 
                          tsm.AntennaStatus = 1;
                          for (p=0; p<3; p++)
                          {
                            if (status_results.antenna.iBiteFaults[p] & fault_array[1][p])
                            {
                              tsm.AntennaStatus = 0;
                              break;
                            }
                          }
                        }
                        if (tmp_status != tsm.AntennaStatus) send_tsm = 1;
                      }

                      sprintf(log_str, "Received STATUS product %s from socket %d - %s\n", 
                                prod_file_name, j, status_sitename);
                      Lprintf(log_str);

                      answer = fread(&status_results, 1, STATUS_RESULTS_SIZE, prod_file);
                    break;
  
                    default:
                      sprintf(log_str, "Received a notification of another type of product: %s\n", 
                        prod_file_name);
                      Lprintf(log_str);
                    break;
                  } /* end switch */
                  fclose(prod_file);
                } /* end fopen */
                else
                {
                  sprintf(log_str, "Unable to open the product: %s\n", prod_file_name);
                  Lprintf(log_str);
                }
                sprintf(del_string, "rm -f %s*", prod_file_name);
                system(del_string); 
              } /* end if FILE */
              else
              {
                sprintf(log_str, "Received unknown string from IRIS notification server: %s\n", 
                          buf_str[i]);
                Lprintf(log_str);
              }
            } /* end for count of messages on socket */
          } /* end offset > 0 */
          else if (offset == 0)
          {
            close(iris_ms[j]);
            iris_ms[j] = 0;
            sprintf(log_str, "Closing connection to IRIS notification socket %d.  Recv returned 0.\n", j);
              
            Lprintf(log_str);
          }
          else
          {
            close(iris_ms[j]);
            iris_ms[j] = 0;
            sprintf(log_str, 
              "Error errno = %d when reading IRIS notification socket %d.  Closing connection.\n",
                  errno, j);
            Lprintf(log_str);
          }
        } /* end if this socket has something for reading */
      } /* end for all sockets checked on this select */
      for (i=0; i<5; i++)
      {
        if (iris_ms[i] > 0) FD_SET(iris_ms[i], &afds);
      }
      tv.tv_sec = 0;
      tv.tv_usec = 0;
      answer = select(32, &afds, NULL, NULL, &tv);
    } /* end while sockets to read */


    /*****
      5) Check to see what is the online channel, and send mode change command if necessary.
    *****/
    now_time = time(NULL);
    /* If A is in MON or HAZ, declare it online.  Else If B is in MON or HAZ, declare it online.
       Else, declare A online */
    tmp_status1 = tsm.OnlineChannel;
    tmp_status2 = tsm.ScanMode;
    if (scanmode_a > 0) 
    {
      tsm.OnlineChannel = 1;
      tsm.ScanMode = scanmode_a;
    }
    else if (scanmode_b > 0) 
    {
      tsm.OnlineChannel = 2;
      tsm.ScanMode = scanmode_b;
    }
    else
    {
      tsm.OnlineChannel = 1;
      tsm.ScanMode = 0;
    }
    if (tmp_status2 != tsm.ScanMode) send_tsm = 1;

    if ( send_mode || (now_time - mode_time > 60) )
    {
      /* Send a Mode Change command to IRIS, as the online channel status changed */
      if (connected_iris_mode)
      {
	if (scanmode_a == 0 && scanmode_b == 0)
        {
          strcpy(report_mode, "MODE PASSTHRU");
        }
	else
	{
          if ( (tsm.OnlineChannel == 1 && channel_str[0] == 'A') ||
               (tsm.OnlineChannel == 2 && channel_str[0] == 'B') )
          {
            strcpy(report_mode, "MODE ACTIVE");
          }
	  else
  	  {
            strcpy(report_mode, "MODE INACTIVE");
	  }
        } 
        answer = send(iris_mode_s, report_mode, strlen(report_mode)+1, 0);
        sprintf(log_str, "Sending %s to IRIS mode change server.\n", report_mode);
        Lprintf(log_str);
        if (answer < 0)
        {
          sprintf(log_str, "Error errno = %d in sending to mode change messages\n.", errno);
          Lprintf(log_str);
        } 
      }
      send_tsm = 1;
      mode_time = now_time;
      send_mode = 0;
    }

    tmp_status = tsm.RPG1Status;
    if (now_time - rpg1_time > 150)
    {
      tsm.RPG1Status = 0;
      rpg1_time = now_time;
    }
    if (tmp_status != tsm.RPG1Status) send_tsm = 1;

    tmp_status = tsm.RPG2Status;
    if (now_time - rpg2_time > 150)
    {
      tsm.RPG2Status = 0;
      rpg2_time = now_time;
    }
    if (tmp_status != tsm.RPG2Status) send_tsm = 1;

    tmp_status1 = tsm.RDA1Status;
    tmp_status2 = tsm.Channel1Status;
    if (now_time - rda1_time > 150) 
    {
      tsm.RDA1Status = 0;
      tsm.Channel1Status = 2;
      rda1_time = now_time;
      scanmode_a = 0;
    }
    if (tmp_status1 != tsm.RDA1Status) send_tsm = 1;
    if (tmp_status2 != tsm.Channel1Status) send_tsm = 1;

    tmp_status1 = tsm.RDA2Status;
    tmp_status2 = tsm.Channel2Status;
    if (now_time - rda2_time > 150)
    {
      tsm.RDA2Status = 0;
      tsm.Channel2Status = 2;
      rda2_time = now_time;
      scanmode_b = 0;
    }
    if (tmp_status1 != tsm.RDA2Status) send_tsm = 1;
    if (tmp_status2 != tsm.Channel2Status) send_tsm = 1;

    if ((now_time -  tsm_time) >= 60) send_tsm  = 1; 
    if ((now_time - awwm_time) >= 86400) send_awwm = 1; 


    /*****
      6) If we need to, send out the messages to IWHU! 
    *****/
    /* if we are the online channel, then we send the messages, else we don't */
    if ( (tsm.OnlineChannel == 1 && channel_str[0] == 'A') ||
         (tsm.OnlineChannel == 2 && channel_str[0] == 'B') )
    {
      if (send_tsm)
      {
	struct tm now_tm;

        Lprintf("Sending TSM\n");
        localtime_r(&now_time,&now_tm);
        sprintf(tmp_str, "00%d", (now_tm.tm_mon)+1);
        strcpy(mon_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "00%d", now_tm.tm_mday);
        strcpy(day_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "00%d", now_tm.tm_hour);
        strcpy(hou_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "00%d", now_tm.tm_min);
        strcpy(min_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "00%d", now_tm.tm_sec);
        strcpy(sec_str, &tmp_str[strlen(tmp_str)-2]); 

        sprintf(tmp_str, "%d%s%s%s%s%s00", (now_tm.tm_year)+1900, mon_str,
                  day_str, hou_str, min_str, sec_str);
        memcpy(tsm.Timestamp, tmp_str, 16);

        sprintf(tmp_str, "000%d", tsm_count);
        tsm_count = (tsm_count + 1) % 10000;
        sprintf(file1_str, "tsm%s.dat", &tmp_str[strlen(tmp_str)-4]);
        sprintf(file2_str, "/usr/iris_data/temp/.%s", file1_str);
        out_file = fopen(file2_str, "w+b");
        fwrite(&tsm, 1, 16, out_file);
        tmp_status = htonl(tsm.Channel1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.Channel2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.OnlineChannel);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.ScanMode);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RPG1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RPG2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RDA1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RDA2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RSP1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RSP2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.XMT1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.XMT2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RCP1Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.RCP2Status);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.AntennaStatus);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.WindAlert);
        fwrite(&tmp_status, 1, 4, out_file);
        tmp_status = htonl(tsm.StormAlert);
        fwrite(&tmp_status, 1, 4, out_file);
        fclose(out_file);
        sprintf(tmp_str, "rcp %s %s:%s/.%s\n 1>/dev/null 2>/dev/null",
                    file2_str, iwhu_name, tsm_dir, file1_str);
        system(tmp_str);
        sprintf(tmp_str, "remsh %s 'mv -f %s/.%s %s/%s\n 1>/dev/null 2>/dev/null' 1>/dev/null 2>/dev/null", 
                    iwhu_name, tsm_dir, file1_str, tsm_dir, file1_str);
        system(tmp_str);
        sprintf(tmp_str, "rm -f %s 1>/dev/null 2>/dev/null\n", file2_str);
        system(tmp_str);

        tsm_time = now_time;
        send_tsm = 0;
      }
      if (send_awwm)
      {
	struct tm now_tm;
        Lprintf("Sending AWWM\n");
        localtime_r(&now_time,&now_tm);
        sprintf(tmp_str, "0%d", (now_tm.tm_mon)+1);
        strcpy(mon_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "0%d", now_tm.tm_mday);
        strcpy(day_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "0%d", now_tm.tm_hour);
        strcpy(hou_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "0%d", now_tm.tm_min);
        strcpy(min_str, &tmp_str[strlen(tmp_str)-2]); 
        sprintf(tmp_str, "0%d", now_tm.tm_sec);
        strcpy(sec_str, &tmp_str[strlen(tmp_str)-2]); 

        sprintf(tmp_str, "%d%s%s%s%s%s00", (now_tm.tm_year)+1900, mon_str,
                  day_str, hou_str, min_str, sec_str);
        memcpy(awwm.Timestamp, tmp_str, 16);

        sprintf(tmp_str, "000%d", awwm_count);
        awwm_count = (awwm_count + 1) % 10000;
        sprintf(file1_str, "awwm%s.dat", &tmp_str[strlen(tmp_str)-4]);
        sprintf(file2_str, "/usr/iris_data/temp/.%s", file1_str);
        out_file = fopen(file2_str, "w+b");
        fwrite(&awwm, 1, 16, out_file);
        for (i=1; i<5; i++)
        {
          fwrite(&(awwm.Runway[i]), 1, sizeof(struct Runway) - 8, out_file);
        }
        fclose(out_file);
        sprintf(tmp_str, "rcp %s %s:%s/.%s\n 1>/dev/null 2>/dev/null",
                    file2_str, iwhu_name, awwm_dir, file1_str);
        system(tmp_str);
        sprintf(tmp_str, "remsh %s 'mv -f %s/.%s %s/%s\n 1>/dev/null 2>/dev/null' 1>/dev/null 2>/dev/null", 
                    iwhu_name, awwm_dir, file1_str, awwm_dir, file1_str);
        system(tmp_str);
        sprintf(tmp_str, "rm -f %s 1>/dev/null 2>/dev/null\n", file2_str);
        system(tmp_str);

        awwm_time = now_time;
        send_awwm = 0;
      }
    }
    
    /*****
      PACE THE LOOP!
    *****/
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    answer = select(32, NULL, NULL, NULL, &tv);
  } /* end while(1) */
}

static void sighup_handler(int signal_a)
{
  action.sa_handler = sighup_handler;
  sigemptyset( &action.sa_mask );
  action.sa_flags = SA_RESTART;
  sigaction( SIGHUP, &action, NULL );
}

void Lprintf(const char *log_str)
{
  if (!logging) return;
  fprintf(log_file, "%s", log_str);
  fflush(log_file);
  return;
}

static void sigio_handler( int signal_a )
{
  struct sigaction action;
  char data[100];
  int isize;

  isize = recv( iris_mode_s, data, 99, 0 );
  if (isize > 0)
  {
    /* We got some valid data here.  Add terminating NULL, then process */
    data[isize] = 0;
    if (0 == strcmp( data, "NOP" ))
    {
    }
    else if (0 == strcmp( data, "EXIT" ))
    {
    }
    else
    {
      sprintf(log_str, "recv read unknown message: '%s' from IRIS mode change server.\n", data );
      Lprintf(log_str);
    }
  }
  else if (isize < 0)
  {
    if (errno != EWOULDBLOCK)
    {
      sprintf(log_str, "recv error errno = %d from IRIS mode change server.\n", errno);
      Lprintf(log_str);
    }
  }
  else
  {
    /* Zero size indicates that the socket has been closed at the other end */
    Lprintf ("Link broken to IRIS mode change server - closing connection.\n");
    action.sa_handler = SIG_IGN;
    sigemptyset( &action.sa_mask );
    action.sa_flags = SA_RESTART;
    sigaction( SIGIO, &action, NULL );
    connected_iris_mode = 0;
    close(iris_mode_s);
    iris_mode_s = 0;
  }
  return;
}
