/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  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 program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        comm_monit.c
.LANGUAGE    C
.AUTHOR      C. Guirao ESO-SDAG 
.COMMENTS    Module to get messages from MIDAS monitor via local 
	     socket and interrupts.
.VERSION     [1.1] 940608  CG. Implementation.

 090818		last modif
------------------------------------------------------------*/
/*
 * Define _POSIX_SOURCE to indicate
 * that this is a POSIX program
 */
#define _POSIX_SOURCE 1

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <osxdef.h>
#include <proto_os.h>         /* ANSI-C prototyping */

char *osmsg();

void open_monit_connection();

static int xhelp_fd;
static char *channame[2] = { (char *)NULL, (char *)NULL };
static char acknowledge = 1;
extern char contxt[];

static void interrupt_msg(signal)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Read a message from the MIDAS monitor containing
 	 changes in the context list.
.RETURNS void
------------------------------------------------------------*/
int signal;
{
  int num_char;
  char *indx;
  /* MAX_CONTXT * 8 + 2 = 15*8 + 2 = 122 < len(argv[6]) = 160 */
  char buffer[164];
  int GetHelp();
  int len;

  if (signal == SIGUSR1) len = 20;
  else len = 164;			/* SIGUSR2 ( MAX_CONTXT * 8 + 2 ) */

  /* If signal received, try to read, otherwise reconnect */
  open_monit_connection(); 

  if ((num_char = osxread(xhelp_fd,buffer,len)) != len) {
    osxclose(xhelp_fd);
    open_monit_connection();
    return;
    }
  if (signal == SIGUSR1 ) {
    /* printf ("command=%s\n",buffer); */
    if ((indx = strchr(buffer,' ')) != (char *)NULL ) *indx = '\0';
    GetHelp(buffer,"C",1);
    }
  else 
    { 
    /* printf ("context=%s\n",buffer);  */
    strcpy(contxt,buffer);	/* SIGUSR2 */
    }
  osxwrite(xhelp_fd,&acknowledge,1);
}

static void int_usr1(sig)
int sig;
{
  /* printf("SIGUSR1\n"); */
  interrupt_msg(SIGUSR1);
}
static void int_usr2(sig)
int sig;
{
  /* printf("SIGUSR2\n"); */
  interrupt_msg(SIGUSR2);
}

int init_monit_connection()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Initiate a connection with the MIDAS monitor.
.RETURNS 0 is OK, -1 if error.
------------------------------------------------------------*/
{
  int xhelp_pid, n;
  char *mid_work, *dazunit;
  struct stat buf;
  FILE *fd;
  struct sigaction act;


  if (!(mid_work = getenv("MID_WORK"))) return(-1);

  channame[1] = malloc((size_t)(strlen(mid_work)+strlen("xhelp")+2+strlen("_pid")+1)); 

  if (!(dazunit = getenv("DAZUNIT"))) { 
    free(channame[1]);
    channame[1] = (char *)NULL;
    return(-1);
    }

  /* Open a file in $MIDWORK/xhelp$DAZUNIT_pid , and write the pid */
  sprintf(channame[1],"%s%s%s%s",mid_work,"xhelp",dazunit,"_pid");

  /* Only if it does not exist */
  if (stat(channame[1],&buf) == 0) return(-1);

  if ( (fd = fopen(channame[1],"w")) == (FILE *)NULL) {
  free(channame[1]);
    channame[1] = (char *)NULL;
    return(-1);
    }

  xhelp_pid = getpid();
  fprintf(fd,"%d\n",xhelp_pid);
  fclose(fd);

  n = strlen(channame[1]) - strlen("_pid");
  channame[0] = malloc((size_t)(n+1));
  strncpy(channame[0],channame[1],n);
  channame[0][n] = '\0';

  /* set int_usr1 as interrupt routine for SIGUSR1 but blocks SIGUSR2 */
  act.sa_handler = int_usr1;
  sigemptyset(&act.sa_mask);
  sigaddset(&act.sa_mask,SIGUSR2);
  act.sa_flags = 0;
  sigaction(SIGUSR1,&act,NULL);

  /* set int_usr2 as interrupt routine for SIGUSR2 but blocks SIGUSR1 */
  act.sa_handler = int_usr2;
  sigemptyset(&act.sa_mask);
  sigaddset(&act.sa_mask,SIGUSR1);
  act.sa_flags = 0;
  sigaction(SIGUSR2,&act,NULL);
return 0;
}

void open_monit_connection()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Open the connection with the MIDAS monitor.
.RETURNS void
------------------------------------------------------------*/
{
  if (channame[0]) {
    if (xhelp_fd == 0) {
      if ((xhelp_fd = osxopen(channame,LOCAL|IPC_WRITE)) == -1) {
        printf("\n\rXHELP: Cannot open client socket: %s\n\r",osmsg());
        xhelp_fd = 0;
        }
      }
    }
}


void close_monit_connection()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Close the connection with the MIDAS monitor.
.RETURNS void
------------------------------------------------------------*/
{
  if (channame[0]) {
    if (xhelp_fd != 0) {
      osxclose(xhelp_fd);
      xhelp_fd=0;
      }
    unlink(channame[1]); 
    free(channame[0]);
    free(channame[1]);
    }
}
