/*===========================================================================
  Copyright (C) 1995-2005 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
===========================================================================*/

/*+++++++++++++++   MIDAS monitor/osx server routines +++++++++++++++++++++++++
.LANGUAGE    C
.IDENTIFICATION  Module PREPZ1
  that's the server end of a client <-> server setup via sockets
  the corresponding client software is in the file
                           $MIDASHOME/$MIDVERS/libsrc/xcon/client.c
.AUTHOR  K. Banse               ESO - Garching
.KEYWORDS
  MIDAS monitor
.COMMENTS
  holds  ServInit, ServRead, ServWrite, ServKWrite, ServClose
.ENVIRONMENT  VMS and UNIX

.VERSION  [1.00] 940426:  first working version for On-Line Midas

 051021		last modif

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

#include <stdlib.h>
#include <fileexts.h>
#include <osyparms.h>
#include <idiserver.h>

static char    myunit[4], *oxpntr;
static char    *servername[2] = { (char *)NULL, (char *)NULL };

static int     n_bytes = 0;      /* number of transmitted bytes  */
static  int    osxchan;
static int     paksize;
static int     osx_cod, first_bytes, jsecs, msecs;
static int     osxi, oldsxi, mode;

/*

*/

int ServInit(chost,retosx)
char *chost;
int  *retosx;

{
int  kk, port;


OSY_GETSYMB("DAZUNIT",myunit,4);
myunit[2] = '\0';

oserror = 0;

first_bytes = BUFHEAD;
jsecs = 1;
msecs = 0;

if (chost[0] == '\0')
   {
   char   *pipedir, filename[128];

   if (!(pipedir = getenv("MID_WORK")))
      {
      (void) printf
             ("ServInit: MID_WORK not defined - we use $HOME/midwork/ ...\n");
      if (!(pipedir = getenv("HOME"))) return (-1);

      (void) strcpy(filename,pipedir);
      (void) strcat(filename,"/midwork");
      }
   else
      (void) strcpy(filename,pipedir);

   (void) strcat(filename,"/Midas_osx");
   (void) strcat(filename,myunit);       /* filename: $MID_WORK/Midas_osxXY */
   kk = (int)strlen(filename) + 1;
   servername[0] = malloc((size_t)kk);
   (void)strcpy(servername[0],filename);
   mode = LOCAL | IPC_READ;
   }

else
   {
   kk = (int)strlen(BASE_PORT) + 1;
   servername[0] = malloc((size_t)kk);
   if ( (port = osxgetservbyname(BASE_SERVICE)) == -1) 
      (void) sprintf(servername[0],"%d",atoi(BASE_PORT) + atoi(myunit));
   else 
      (void) sprintf(servername[0],"%d",port + atoi(myunit));
   mode = NETW | IPC_READ;
   }


/* Open server channel for reading. */

osxchan = osxopen(servername, mode);


free(servername[0]);
if ( osxchan == -1)
   {                            /* we need to look at `oserror' */
   *retosx = oserror;
   if (oserror == -1)
      (void) printf("ServInit: osxopen produced: %s\n",oserrmsg);
   else
      (void) printf("ServInit: osxopen produced: %s\n",osmsg());
   return(-1);
   }

osxi = NOCONN;

memset((char *)&serv_buf,0,sizeof(serv_buf));   /* init structures */
memset((char *)&serv_ret,0,sizeof(serv_ret));

return(0);
}

/*

*/

int  ServRead(comline,maxcom,fcode,retosx)
char  *comline;
int   maxcom, *fcode, *retosx;

{
int  nn;

char  *charbuf;



osx_poll:
oldsxi = osxi;
osxi = osxinfo(osxchan,jsecs,msecs);	/* see, if something to read  (UNIX) */
if ( (osxi == NOCONN) || (osxi == NODATA) )  goto osx_poll;


/*  o.k., so read the stuff */

oxpntr = (char *) &serv_buf;
osx_cod = osxread (osxchan,oxpntr,first_bytes);

if (osx_cod == -1)
   {
   *retosx = oserror;
   return(-1);
   }

if (osx_cod < first_bytes) goto osx_poll;
                        
*fcode = serv_buf.code_id;	       /* get function code sent from client */
n_bytes = serv_buf.nobyt - BUFHEAD;    /*  get remaining bytes  */


/* if EXIT, close output channel  */

if (serv_buf.code_id == EXIT_CODE) 
   {
   osxclose (osxchan);
   return (0);				/* successful disconnection */
   }

 
oxpntr = (char *) &serv_buf.data;
osx_cod = osxread(osxchan,oxpntr,n_bytes);
if (osx_cod == -1)
   {
   *retosx = oserror;
   return(-1);
   }

   
charbuf = (char *) (serv_buf.data.in);
nn = (int) strlen(charbuf);
if (nn >= maxcom)			/* command line overflow */
   {
   char  tmpbuf[80];

   (void) sprintf
   (tmpbuf,"ServRead - Warning: command line (length = %d) truncated",nn);
   SCTPUT(tmpbuf);
   *(charbuf+maxcom-1) = '\0';
   }

(void) strcpy(comline,charbuf);
return(0);
}

/*

*/

int ServWrite(status,retosx)
int  status;				/* IN: status to be returned */
int  *retosx;				/* OUT: osx return stat */

{
serv_ret.code = status;
paksize = RET_SIZE;
serv_ret.nobyt = paksize;
 
oxpntr = (char *) &serv_ret;
osx_cod = osxwrite(osxchan,oxpntr,paksize);
if (osx_cod == -1)
   {
   *retosx = oserror;
   return (-1);
   }

return(0);
}

/*

*/

int  ServKRead(typ,sendbuf,karr,retosx)
int    typ;
char   *sendbuf;
int    *karr;                   /* 4 elements */
int    *retosx;

{
register int  nr;



/* send back an o.k. status */

serv_ret.code = 0;
paksize = RET_SIZE;
serv_ret.nobyt = paksize;

oxpntr = (char *) &serv_ret;
osx_cod = osxwrite(osxchan,oxpntr,paksize);
if (osx_cod == -1)
   {
   *retosx = oserror;
   return (-1);
   }


/* and read the data part */

oxpntr = (char *) &serv_buf;
osx_cod = osxread (osxchan,oxpntr,first_bytes);

if (osx_cod == -1)
   {
   *retosx = oserror;
   return(-1);
   }

n_bytes = serv_buf.nobyt - BUFHEAD;    /*  get remaining bytes  */
oxpntr = (char *) &serv_buf.data;
osx_cod = osxread(osxchan,oxpntr,n_bytes);
if (osx_cod == -1)
   {
   *retosx = oserror;
   return(-1);
   }


for (nr=0; nr<4; nr++)
   karr[nr] = serv_buf.data.in[nr];

if (typ == 1)
   {
   int    *ipntr;

   ipntr = (int *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      *ipntr++ = serv_buf.data.in[nr];
   }
else if (typ == 2)
   {
   float  *fpntr;

   fpntr = (float *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      *fpntr++ = serv_buf.data.fl[nr];
   }
else if (typ == 4)
   {
   double *dpntr;

   dpntr = (double *) sendbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      *dpntr++ = serv_buf.data.db[nr];
   }
else
   {
   char  *cpntr;

   cpntr = (char *) &serv_buf.data.in[4];
   (void) strncpy(sendbuf,cpntr,karr[0]);
   }

return(0);
}

/*

*/

int ServKWrite(typ,retbuf,karr,retosx)
int    typ;
char   *retbuf;
int    *karr;                   /* 4 elements */
int    *retosx;

{
register int  nr;
int  m;



for (nr=0; nr<4; nr++)
   serv_ret.data.in[nr] = karr[nr];


/* prepare data buffer */

if (typ == 1) 
   {
   int    *ipntr;

   m = (4 + karr[0]) * III_SIZE;
   ipntr = (int *) retbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_ret.data.in[nr] = *ipntr++;
   }
else if (typ == 2)
   {
   float  *fpntr;

   m = (4 + karr[0]) * RRR_SIZE;
   fpntr = (float *) retbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_ret.data.fl[nr] = *fpntr++;
   }
else if (typ == 4)
   {
   double *dpntr;

   m = (4 + karr[0]) * DDD_SIZE;
   dpntr = (double *) retbuf;
   for (nr=4; nr<karr[0]+4; nr++)
      serv_ret.data.db[nr] = *dpntr++;
   }
else
   {
   char  *cpntr;

   cpntr = (char *) &serv_ret.data.in[4];
   m = karr[0];
   (void) strncpy(cpntr,retbuf,m);
   m += 4*III_SIZE;			/* add the 4 k`karr' integers */
   }


/* and send it to Client */

serv_ret.code = 0;
paksize = RET_SIZE + m;
serv_ret.nobyt = paksize;

oxpntr = (char *) &serv_ret;
osx_cod = osxwrite(osxchan,oxpntr,paksize);
if (osx_cod == -1)
   {
   *retosx = oserror;
   return (-1);
   }

return(0);
}

/*

*/

int ServClose(retosx)
int  *retosx;

{
osx_cod = osxclose(osxchan);
if (osx_cod != 0)
   {
   *retosx = oserror;
   return (-1);
   }
else
   return (0);				/* successful disconnection */
}

