/*  This module contains the subroutines necessary for interproccess 
 *  communication between user applications using the MIIPS modules, 
 *  and the enhanced version of SAOimage (v. 1.07E2) on a UNIX system.
 *  At this time, only communication via pipes is supported.  This 
 *  module was cannabilized from a module written by Jim Wright, System
 *  Programmer at Canada-France-Hawaii Telescope Corp., on November 29, 1993
 *  and slightly modified so that the subroutines could be called by a 
 *  UNIX version of FORTRAN.
 *
 *			Donald Gudehus, September, 1994
 *			Version 2, D. Gudehus, Aug. 24, 2006
 *			Fixed up comparisons between pointer and integer
 */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

#include "si_subs.h"

int si_datain = -1;		/* initially no connection */
int si_dataout = -1;


/*+***********************************************************************
 Function:	si_open_namedpipe_()

 Abstract:	Open communication to SAOimage.

 Description:	This routine looks for the named pipes to talk to SAOimage
		and opens them for use by other routines.  The open file
		descriptors are global.
*-***********************************************************************/

PASSFAIL 
si_open_namedpipe_ () {

    char home[NAMELEN];
    char inname[NAMELEN];
    char outname[NAMELEN];
    struct stat instatbuf;
    struct stat outstatbuf;
    int gotpipes = FALSE;
    char *p;

    /*
     * where is home
     */
    p = (char *) getenv ("HOME");
/*  if (p != NULL && *p != NULL) {    fixed D. H. G. */
    if (p != NULL && *p != 0) {
	strcpy (home, p);
    } else {
	fprintf (stderr, "(si_open_namedpipe_) can't find HOME\n");
	perror ("");
	return (FAIL);
    }

    /*
     * first look in environment
     */
    p = (char *) getenv (INNAME);
    if (p != NULL && *p != 0) {
	strcpy (inname, p);
	p = (char *) getenv (OUTNAME);
	if (p != NULL && *p != 0) {
	    strcpy (outname, p);
	    if (stat (inname, &instatbuf) != -1)
		if (S_ISFIFO (instatbuf.st_mode))
		    if (stat (outname, &outstatbuf) != -1)
			if (S_ISFIFO (outstatbuf.st_mode))
			    gotpipes = TRUE;
	}
    }
    if (!gotpipes) {

	/*
	 * next look in   ~/.imt1?
	 */
	strcpy (inname, home);
	strcat (inname, "/.");
	strcat (inname, I_DEVNAME);
	strcpy (outname, home);
	strcat (outname, "/.");
	strcat (outname, O_DEVNAME);
	if (stat (inname, &instatbuf) != -1)
	    if (S_ISFIFO (instatbuf.st_mode))
		if (stat (outname, &outstatbuf) != -1)
		    if (S_ISFIFO (outstatbuf.st_mode))
			gotpipes = TRUE;
    }
    if (!gotpipes) {

	/*
	 * finally look in   /dev/imt1?
	 */
	strcpy (inname, "/dev/");
	strcat (inname, I_DEVNAME);
	strcpy (outname, "/dev/");
	strcat (outname, O_DEVNAME);
	if (stat (inname, &instatbuf) != -1)
	    if (S_ISFIFO (instatbuf.st_mode))
		if (stat (outname, &outstatbuf) != -1)
		    if (S_ISFIFO (outstatbuf.st_mode))
			gotpipes = TRUE;
    }
    if (!gotpipes) {
	fprintf (stderr, "(si_open_namedpipe_) can't open named pipes\n");
	perror ("");
	return (FAIL);
    }

    /*
     * Open the output fifo.  We have to open it ourselves first as a client to
     * get around the fifo open-no-client error.
     */
    if ((si_datain = open (outname, O_RDONLY | O_NDELAY)) != -1) {
	if ((si_dataout = open (outname, O_WRONLY | O_NDELAY)) != -1) {
	    fcntl (si_dataout, F_SETFL, O_WRONLY);
	} else {
	    fprintf (stderr, "(si_open_namedpipe_) can't open %s\n", outname);
	    perror ("");
	    return (FAIL);
	}
	close (si_datain);
    } else {
	fprintf (stderr, "(si_open_namedpipe_) can't open %s\n", outname);
	perror ("");
	return (FAIL);
    }

    /*
     * Open the input stream, a FIFO pseudodevice file used by applications to
     * send us commands and data.
     */
    if ((si_datain = open (inname, O_RDONLY | O_NDELAY)) != -1) {
	/* Clear O_NDELAY for reading. */
	fcntl (si_datain, F_SETFL, O_RDONLY);
    } else {
	fprintf (stderr, "(si_open_namedpipe_) can't open %s\n", inname);
	perror ("");
	return (FAIL);
    }

    return (PASS);
}

/*+***********************************************************************
 Function:	si_close_namedpipe_()

 Abstract:	Close communication to SAOimage.

 Description:	This routine closes the named pipes to talk to SAOimage.
*-***********************************************************************/

void 
si_close_namedpipe_ () {

    if (si_datain != -1) {
	close (si_datain);
	si_datain = -1;
    }
    if (si_dataout != -1) {
	close (si_dataout);
	si_dataout = -1;
    }
}

/*+***********************************************************************
 Function:	si_write_()				[PRIVATE]

 Abstract:	Write data to SAOimage.

 Description:	Write data to SAOimage.
*-***********************************************************************/

PASSFAIL
si_write_ (buf, size)
    char *buf;
    int *size;
{
    int n = 0;
    int total = 0;

    while (total < *size) {
	n = write (si_dataout, buf, *size - total);
	if (n <= 0) {
	    fprintf (stderr, "(si_write_) can't write\n");
	    perror ("");
	    return (FAIL);
	}
	total += n;
    }
    return (PASS);
}

/*+***********************************************************************
 Function:	si_read_()				[PRIVATE]

 Abstract:	Read data from SAOimage.

 Description:	Read data from SAOimage.
*-***********************************************************************/

PASSFAIL
si_read_ (buf, size)
    char *buf;
    int *size;
{
    if ((*size = read (si_datain, buf, 16384)) <= 0) {
	fprintf (stderr, "(si_read) can't read\n");
	perror ("");
	buf[0] = '\0';
	*size = 0;
	return (FAIL);
    }
    return (PASS);
}
