/*===========================================================================
  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
===========================================================================*/

/*++++++++++++++++++++++++ Module OSY ++++++++++++++++++++++++++
.TYPE            Module
.LANGUAGE        C
.IDENTIFICATION  OSY routines for Unix
.AUTHOR          Benoit  Pirenne, K. Banse   [ESO-IPG]
.KEYWORDS        Operating-system interface
.ENVIRONMENT     uses the os interface routines.
.COMMENTS        OSY routines are useful for the implementation
		 of a first portable version of Midas.
holds  OSY_ASCTIM, OSY_MESSAGE, OSY_GETSYMB, OSY_TRNLOG, OSY_SPAWN
       OSY_TIMER, OSY_SLEEP, OSY_DASSGN, 
		  OSY_WVB, OSY_RVB, OSY_WLDB, OSY_RLDB

.VERSION         [1.0]  861012: Creation.   B. Pirenne

 090428		last modif
----------------------------------------------------------------------------*/
 
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#include <osyparms.h>
#include <fileexts.h>
#include <osparms.h>

static unsigned int  addr;

int  osdofwrite(), osdofread(), osftranslate();

/*  this routine can be used for debugging OSY_WVB, OSY_RVB, if needed ...


static int  osy_read = 0, osy_write = 0;

void OSY_COUNT(rdcount,wrcount)
int  *rdcount, *wrcount;

{
*rdcount = osy_read;
*wrcount = osy_write;
}
*/

/*

*/

int OSY_ASCTIM(time)
/*+++++++++++++++++++++++++ Function OSY_ASCTIM +++++++++++++++++++
.PURPOSE   Gets the  time
.RETURNS   Function  : always zero
.RETURNS   Parameter : the actual time as a pointer to a 26
		       character string containing the day name,
		       complete date and time in day.
------------------------------------------------------------------*/
char  *time;  /* OUT : pointer to a string of char containing the time */

{
int ret;
int oshdate();

struct tm  date_struct;




ret = oshdate(time,&date_struct);
if (ret == 0)
   return ERR_NORMAL;
else 
   {
   MID_ERROR("OSY","OSY_ASCTIM",ret,0);		/* `ret' is just dummy */
   return (ERR_INPINV);
   }
}

/*

*/

void OSY_MESSAGE(mstat,errmsg)
/*+++++++++++++++++++++++ Function OSY_MESSAGE ++++++++++++++++++++++++
.PURPOSE Get and print system message.
.RETURNS Nothing
.REMARKS Print the system message corresponding to the status received.
----------------------------------------------------------------------*/

int mstat;		/* IN: System error number */
char  *errmsg;		/* OUT: buffer for message */

{
extern int  oshmsg();


if (oshmsg(mstat,errmsg) != 0)
   (void)strcpy(errmsg,"SYS_MSG : No system message returned ... ");
}

/*

*/

#ifdef __STDC__
int OSY_TIMER(char action , float * time)
#else
int OSY_TIMER(action, time)
/*+++++++++++++++++++++++++ Function  OSY_TIMER +++++++++++++++++++++++++++++
.PURPOSE Reports the CPU time used.
.RETURNS Function : 0 if the action requested was correct, -1 if the action
		    was not correct.
.RETURNS Parameter : the actual CPU time passed since the Initialisation (in
		     hundreds of seconds).
.REMARKS If action is 'I' then the initialization is done. 
         If it is 'G' then the CPU time is obtained and returned.
----------------------------------------------------------------------------*/
char    action;     /* IN : action : 'I' to initialize; 'G' to get it */
float   *time;      /* OUT: time passed. */
#endif

{
int   oshcpu();
int   ret;

float dum;


switch (action) 
   {
   case 'I' :
    ret = oshcpu(INIT_CPU_CLOCK,&dum);
    break;

   case 'G' :
    ret = oshcpu(GET_CPU_CLOCK,time);
    break;

   default  :
    ret = -1;
   }

if (ret == 0)
   return ERR_NORMAL;
else 
   {
   MID_ERROR("OSY","OSY_TIMER",ret,0);		/* `ret' is just dummy */
   return (ERR_INPINV);
   }
}

/*

*/

int OSY_DASSGN(entrx,iochan)
/*+++++++++++++++++++++++++ Function  OSY_DASSIGN +++++++++++++++++++++++++++++
.PURPOSE Deassign a channel (close a file)
.RETURNS Function : 0 if the action requested was correct, -1 if the action
		    was not correct.
----------------------------------------------------------------------------*/

int entrx		/* FCT entry, if >= 0  */;
int iochan	 	/* channel number (file identifier in Unix) */;

{
int   status, chanl;


struct FCT_STRUCT  *fctpntr;
    

if (entrx < 0)
   status = close(iochan);

else
   {
   fctpntr = FCT.ENTRIES + entrx;
   chanl = fctpntr->IOCHAN;

   if (chanl < 0)			/* it's a memory file */
      {
      int  idx;

      idx = -1 - chanl;                 /* recalculate VMEM index */
      (void) MID_VMEM(3,idx,&status);
      return (ERR_NORMAL);
      }


   status = close(chanl);
   }

if (status == -1)
   {
   MID_ERROR("OSY","OSY_DASSGN",status,0);	/* `status' is just dummy */
   return (ERR_INPINV);
   }
else 
   return (ERR_NORMAL);
}
/*

*/

int OSY_WVB(iochan,pbuf,nobyt,vbn)
/*++++++++++++++++++++++++++ Function OSY_WVB +++++++++++++++++++++++++

.PURPOSE write virtual blocks to disk or memory
.RETURNS midas error code
.REMARKS uses the os interface service osdofwrite.

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

int   iochan;	/* IN : file identifier assigned to disk file */
char  *pbuf;	/* IN : pointer to the buffer to write */
unsigned int nobyt;	/* IN : number of bytes to be transferred */
int   vbn;	/* IN : starting virtual block for data transfer */

{
int   status;

off_t  offset;


/* osy_write++; */


if (iochan < 0)
   {
   int idx;

   idx = -1 - iochan;			/* recalculate VMEM index */
   status = MID_VMIO(1,idx,pbuf,nobyt,vbn);
   if (status == ERR_NORMAL) return ERR_NORMAL;
   }

else
   {
   addr = (unsigned int) (vbn - 1);
   addr *= OUR_BLOCK_SIZE;

   offset = (off_t) addr;
   status = osdofwrite(iochan,offset,pbuf,nobyt);
   if (status > 0) return (ERR_NORMAL);
   }

MID_ERROR("OSY","OSY_WVB",-1,0);
return (ERR_INPINV);
}
/*

*/

int OSY_RVB(iochan,pbuf,nobyt,vbn)
/*++++++++++++++++++++++++++ Function OSY_RVB +++++++++++++++++++++++++
.PURPOSE read virtual blocks from disk.
.RETURNS midas error code
.REMARKS uses the os interface service osdofread.
-------------------------------------------------------------------------*/

int   iochan;	/* IN : file identifier assigned to disk file */
char  *pbuf;	/* IN : pointer to buffer to fill from disk */
unsigned int  nobyt;   /* IN : number of bytes to be transferred */
int   vbn;	/* IN : starting virtual block for data transfer */

{
int  status;



/* osy_read++; */


if (iochan < 0)
   {
   int idx;

   idx = -1 - iochan;                 /* recalculate VMEM index */
   status = MID_VMIO(0,idx,pbuf,nobyt,vbn);
   if (status == ERR_NORMAL) return ERR_NORMAL;
   }

else
   {
   addr = (unsigned int) (vbn - 1);
   addr *= OUR_BLOCK_SIZE;

   status = osdofread(iochan,addr,pbuf,nobyt);
   if (status > 0) return (ERR_NORMAL);
   }

MID_ERROR("OSY","OSY_RVB",-1,0);
return (ERR_INPINV);
}
/*

*/

int OSY_WLDB(iochan,pbuf,vbn)
/*++++++++++++++++++++++++++ Function OSY_WLDB +++++++++++++++++++++++++

.PURPOSE write LDB to disk or memory
.RETURNS midas error code
.REMARKS uses the os interface service osdofwrite.

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

int   iochan;	/* IN : file identifier assigned to disk file */
char  *pbuf;	/* IN : pointer to the buffer to write */
int   vbn;	/* IN : starting virtual block for data transfer */

{
int   status;



/* osy_write++; */


if (iochan < 0)
   {
   int idx;

   idx = -1 - iochan;			/* recalculate VMEM index */
   status = MID_VMIO(1,idx,pbuf,(unsigned int)LDB_SIZE,vbn);
   if (status == ERR_NORMAL) return ERR_NORMAL;
   }

else
   {
   addr = (unsigned int) (vbn - 1);
   addr *= OUR_BLOCK_SIZE;

   status = osdofwrite(iochan,addr,pbuf,(unsigned int)LDB_SIZE);
   if (status > 0) return (ERR_NORMAL);
   }

MID_ERROR("OSY","OSY_WLDB",-1,0);
return (ERR_INPINV);
}
/*

*/

int OSY_RLDB(iochan,pbuf,vbn)
/*++++++++++++++++++++++++++ Function OSY_RLDB +++++++++++++++++++++++++
.PURPOSE read LDB from disk.
.RETURNS midas error code
.REMARKS uses the os interface service osdofread.
-------------------------------------------------------------------------*/

int   iochan;	/* IN : file identifier assigned to disk file */
char  *pbuf;	/* IN : pointer to buffer to fill from disk */
int   vbn;	/* IN : starting virtual block for data transfer */

{
int  status;



/* osy_read++; */


if (iochan < 0)
   {
   int idx;

   idx = -1 - iochan;                 /* recalculate VMEM index */
   status = MID_VMIO(0,idx,pbuf,(unsigned int)LDB_SIZE,vbn);
   if (status == ERR_NORMAL) return ERR_NORMAL;
   }

else
   {
   addr = (unsigned int) (vbn - 1);
   addr *= OUR_BLOCK_SIZE;

   status = osdofread(iochan,addr,pbuf,(unsigned int)LDB_SIZE);
   if (status > 0) return (ERR_NORMAL);
   }

MID_ERROR("OSY","OSY_RLDB",-1,0);
return (ERR_INPINV);
}
/*

*/

int OSY_TRANSLA(name,sysname,lsysout)
/*++++++++++++++++++++++++++ Function OSY_TRNLOG +++++++++++++++++++++++++
.PURPOSE Do logical name translation.
.REMARKS uses the os interface service osftranslate.
.RETURNS 
 length of translated name (if > lsysout, sysname not filled)
 < 1 if no translation
-------------------------------------------------------------------------*/
char  *name;      /* IN: logical file name */
char  *sysname;   /* OUT: physical (system dependant) file name */
int   lsysout;    /* OUT: max. length of sysname */

{
int ret;

char  tmp[256];




/* translate first into temp_buf + get length */

ret = osftranslate(name,tmp);	
if ((ret > 0) && (ret < lsysout))
   {						/* fits into result */
   (void) memcpy(sysname,tmp,(size_t)(ret+1));
   }

return (ret);
}

/*

*/

int OSY_TRNLOG(name,sysname,lsysin,lsysout)
/*++++++++++++++++++++++++++ Function OSY_TRNLOG +++++++++++++++++++++++++
.PURPOSE Do logical name translation.
.REMARKS uses the os interface service osfphname.
.RETURNS midas error code
-------------------------------------------------------------------------*/
char   *name      /* IN: logical file name */;
char   *sysname   /* OUT: physical (system dependant) file name */;
int   lsysin      /* IN: max. length of sysname  */;
int   *lsysout    /* OUT: length of sysname */;

{
int  ret;


ret = osfphname(name,sysname);
if (ret != 0) 
   *lsysout = CGN_COPY(sysname,name);
else
   *lsysout = (int)strlen(sysname);

if ((*lsysout) > lsysin)
   return ERR_INPINV;
else
   return ERR_NORMAL;
}

/*

*/

void OSY_GETSYMB(symbol,resbuf,lrb)
/*++++++++++++++++++++++++++ Function OSY_GETSYMB +++++++++++++++++++++++++
.PURPOSE Do logical name translation.
.RETURNS midas error code
.REMARKS uses the os interface service osftranslate

.ALGORITHM
 if no symbol with given name exists, the original string
 (symbol) is copied to the result buffer
 this function is limited to symbols containing strings 
 of max. 200 chars (incl '\0')

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

char   *symbol;  /* IN : logical symbol to be translated */
char   *resbuf;  /* OUT: result buffer */
int    lrb;      /* IN : maximum length of result buffer */ 

{
int ret;

char  tmp[200];



ret = osftranslate(symbol,tmp);		/* translate + get length */
if (ret > 0) 
   {
   if (ret < lrb)			/* fits into result */
      (void) memcpy(resbuf,tmp,(size_t)(ret+1));
   else
      {
      lrb --;
      (void) memcpy(resbuf,tmp,(size_t)lrb);
      resbuf[lrb] = '\0';
      }
   }
else
   {					/* copy original string */
   lrb --;				/* given maxsize includes the '\0' */
   (void) memcpy(resbuf,symbol,(size_t)lrb);
   resbuf[lrb] = '\0';
   } 
}

/*

*/

int OSY_SLEEP(ms,flag)
/*++++++++++++++++++++++++++ Function OSY_SLEEP +++++++++++++++++++++++++
.PURPOSE Sleep for the given amount of ms.
.RETURNS midas error code
.REMARKS Uses : ospwait()
-------------------------------------------------------------------------*/
unsigned int  ms;	/* IN: milliseconds to sleep */
int  flag;		/* IN: = 0, use ospwait, = 1 use ospuwait */

{

if (flag != 1)
   {
   ms -- ;
   return (ospwait((ms / 1000) + 1));
   }
else
   {
   return (ospuwait(ms*1000));
   }
}

/*

*/

int OSY_SPAWN(cmd, phname, procname, maxtime, pid)
/*++++++++++++++++++++++++++ Function OSY_SPAWN +++++++++++++++++++++++++++
.PURPOSE Spawn a subprocess.
.RETURNS midas error code 
.REMARKS Uses : ospcreate.
-------------------------------------------------------------------------*/

int  cmd;		/* IN: 0 = wakeup father on termination (forgr.) 
			       1 = set event flag on termination (backgr.) */
char *phname;		/* IN: Physical name of the file to execute */
char *procname;		/* IN: Name of process */
int  maxtime;		/* IN: max. no. of seconds to wait,
			       = 0, for no timeout */
int  *pid;		/* OUT: pid */

{

*pid = ospcreate(phname,procname,cmd,0,1,(unsigned int)maxtime);

if (*pid == -1)
   return (ERR_OPSSYS);
else
   return (ERR_NORMAL);

}
