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

 000703		last modif

===========================================================================*/

#include <midas_def.h>
#include <secdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <iodef.h>


#define  BIT_0 0x1


static int   status, n, ii, mm;

static short int iosb[4];

static char  msg[260];

/*

*/

void OSY_MESSAGE(statsys,errmsg)
 
/* ++++++++++++++++++++++++++++++++++++++++++++++++++
 
 .IDENTIFICATION
   function OSY_MESSAGE		C-version 1.00	870804
   K. Banse			ESO - Garching
 
 .KEYWORDS
   system messages
 
 .PURPOSE
   display system message for given status
 
 .ALGORITHM
   use system service SYS$GETMSG
   !!! this code is operating system dependant !!!
 
 .INPUT/OUTPUT
   use as  OSY_MESSAGE(status,errmsg)
 
   input par:
   statsys:	int		status code
   errmsg:	char *		buffer for message (should be >= 80)
 
 -------------------------------------------------- */
	
int   statsys;
char  *errmsg;
 
{
int   msglen;

static int rms_errcnt = 9;
static int rms_erros[] = {0x1c0dc, 0x1c04a,
                          0x1c00a, 0x184c4, 
                          0x184cc, 0x1828a,
                          0x18292, 0x18544,
                          0x1829a};
static char  *rms_errmsg[] = {"Cannot close file.","Directory not found.",
                              "File creation error.","Bad device (type).",
                              "Error in directory name.","File is locked.",
                              "File is not found.","Device full.",
                              "Not matching file protection."};
                             

char   byte_array[4];
  
struct dsc$descriptor_s name_descr1;
 

/* set up the VAX-11 descriptor structure */
 
name_descr1.dsc$b_class = DSC$K_CLASS_S;
name_descr1.dsc$b_dtype = DSC$K_DTYPE_T;


/* now execute the system service  */
 
msglen = 0;
ii = SYS$GETMSG(statsys,&msglen,&name_descr1,15,byte_array);


if (ii & BIT_0) 
   {
   (void) strncpy(errmsg,name_descr1.dsc$a_pointer,msglen);
   errmsg[msglen] = '\0';
   }
else
   {
   for (n=0; n<rms_errcnt; n++)
      {
      if (statsys == rms_erros[n])
         {
         (void)strcpy(errmsg,rms_errmsg[n]);
         return;
         }
      }

   (void)strcpy(errmsg,"SYS$GETMSG: no message returned...");
   }
 
}

/*

*/

int OSY_SLEEP(millisec,flag)
 
unsigned int   millisec;
int  flag;		/* not used, just for compatibility with Unix */

{
int   time[2];



time[1] = -1;
time[0] = - (10000 * millisec); 
 
mm = SYS$SETIMR(1,time,0,0);

if (mm & BIT_0) 
   mm = SYS$WAITFR(1);

return mm;
}

/*

*/

int OSY_SPAWN(mailbox_name,process,outterm,pid,astmodule,astparm)
 
/*
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  OSY_SPAWN			C-version 1.00	870723
C  K. Banse                   	ESO - Garching
C
C.KEYWORDS
C  process creation
C
C.PURPOSE
C  create a subprocess
C
C.ALGORITHM
C  use LIB$SPAWN to do the job
C  A mailbox is used for input to the subprocess, output goes to stdio
C
C.INPUT/OUTPUT
C  use as   OSY_SPAWN(mailbox_name,process,outterm,pid,astmodule,astparm)
C
C  input par:
C  mailbox_name: char. string	physical name of mailbox
C  process:	char. string	name of subprocess
C  outterm:	char. string	output stream
C  astmodule:	pointer		pointer to astmodule (a function)
C  astparm:	int		parameter to astmodule
C	
C  output par:
C  pid:		int		process identification no.
C
C-------------------------------------------------------
C
*/

int   *pid, (* astmodule)(), *astparm;
char	*mailbox_name, *process, *outterm;

{
 
struct dsc$descriptor_s name_descr1, name_descr2, name_descr3, name_descr4;
 
int   zero;

static int   icomst; 
 
char	buf1[5];


/* set up the VAX-11 descriptor structure  for mailbox  and  process  */
 
name_descr1.dsc$w_length = strlen(mailbox_name);
name_descr1.dsc$a_pointer = mailbox_name;
name_descr1.dsc$b_class = DSC$K_CLASS_S;
name_descr1.dsc$b_dtype = DSC$K_DTYPE_T;

name_descr2.dsc$w_length = strlen(process);
name_descr2.dsc$a_pointer = process;
name_descr2.dsc$b_class = DSC$K_CLASS_S;
name_descr2.dsc$b_dtype = DSC$K_DTYPE_T;

strcpy(buf1,"$! ");
name_descr3.dsc$w_length = strlen(buf1);
name_descr3.dsc$a_pointer = buf1;
name_descr3.dsc$b_class = DSC$K_CLASS_S;
name_descr3.dsc$b_dtype = DSC$K_DTYPE_T;

name_descr4.dsc$w_length = strlen(outterm);
name_descr4.dsc$a_pointer = outterm;
name_descr4.dsc$b_class = DSC$K_CLASS_S;
name_descr4.dsc$b_dtype = DSC$K_DTYPE_T;
 
/* now execute the system service  */
 
mm = 1;
zero = 0;

status = LIB$SPAWN(&name_descr3,&name_descr1,&name_descr4,
                   &mm,&name_descr2,pid,&icomst,&zero,
                   astmodule,astparm);

if (status & BIT_0) 
   return ERR_NORMAL;
else
   return (-1);
}

/*

*/

int OSY_TIMER(t_action,time)
 
/*
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  OSY_TIMER			C-version 1.00	880706
C  K. Banse			ESO - Garching
C
C.KEYWORDS
C  CPU time
C
C.PURPOSE
C  handle CPU timing
C
C.ALGORITHM
C  use VAX/VMS library functions LIB$INIT_TIMER + LIB$STAT_TIMER
C  !!! this code is operating system dependant !!!
C
C.INPUT/OUTPUT
C  use as status = OSY_TIMER(ACTION,TIME)
C
C  input par:
C  t_action:	character	'I' for initializing 
C				'G' for getting the time
C  output par:
C  *time:	float		time in hundreds of seconds
C 
C  return value:
C  status:	int		return status
C
C--------------------------------------------------
C
*/
	
char	t_action;
float   *time;
 
{
int   itime, two;



if (t_action == 'I')
   status = LIB$INIT_TIMER();
else
   {
   two = 2;
   status = LIB$STAT_TIMER(&two,&itime);
   *time = (float) itime;
   }
 
if ( status & BIT_0 )
   status = ERR_NORMAL;
else
   {
   MID_ERROR("OSY","OSY_TIMER",status,0);
   status = ERR_OPSSYS;
   }
 
return status;
}
/*

*/

int OSY_TRNLOG(name,vmsname,lvmsin,lvmsout)
/*
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  OSY_TRNLOG			version 1.20	871102
C  K. Banse                   	ESO - Garching
C  1.30    900115	1.35	900213
C
C.KEYWORDS
C  logical names
C
C.PURPOSE
C  Do logical name translation.
C
C.ALGORITHM
C  Logical name translation is performed via SYS$TRNLOG.
C  Recursive translation is done by VMS now (from version 3.0 on...).
C
C.INPUT/OUTPUT
C  use as   OSY_TRNLOG(name,vmsname,lvmsin,lvmsout)
C
C  input par:
C  name:	char. string	logical file name (terminated by \0)
C  lvmsin:	int		"real" length of vmsname
C	
C  output par:
C  vmsname:	char. exp.	VMS file name 
C  lvmsout:	int		length of vmsname after translation
C
C.VERSION
C  1.30		put in conversion to upper case
C-------------------------------------------------------
C
*/

int   lvmsin, *lvmsout;
char	*name, *vmsname;

{
 
struct dsc$descriptor_s name_descr1, name_descr2;
 
int   byt1, byt2, c, cdif; 
 

/* make sure we only have upper case stuff ...   */

cdif = 'A' - 'a';
for (n=0; name[n] != '\0'; n++)
   {
   c = name[n];
   if (c == ' ') break;			/* no trailing blanks...!  */
   if ((c >= 'a') && (c <= 'z'))
      msg[n] = c + cdif;
   else
      msg[n] = c;
   }
msg[n] = '\0';


/* set up the VAX-11 descriptor structure */
 
name_descr1.dsc$w_length = n;
name_descr1.dsc$a_pointer = msg;
name_descr1.dsc$b_class = DSC$K_CLASS_S;
name_descr1.dsc$b_dtype = DSC$K_DTYPE_T;


name_descr2.dsc$w_length = lvmsin;
name_descr2.dsc$a_pointer = vmsname;
name_descr2.dsc$b_class = DSC$K_CLASS_S;
name_descr2.dsc$b_dtype = DSC$K_DTYPE_T;

 
/* now execute the system service  */
 
*lvmsout = 0;
status = SYS$TRNLOG(&name_descr1,lvmsout,&name_descr2,&byt1,&byt2,0);

if (*lvmsout > lvmsin)
   status = ERR_INPINV;
else
   {
   vmsname[*lvmsout] = '\0';   
   status = ERR_NORMAL;
   }
 
return status;
 
}

/*

*/

int OSY_WAKE()

{

status = SYS$WAKE(0,0);

if (status & BIT_0) 
   status = ERR_NORMAL;
else
   {
   MID_ERROR("'OSY","OSY_WAKE",status,1);
   status = ERR_INPINV;
   }

return status;

}

/*

*/

int OSY_WVB(iochan,pbuf,nobyt,vbn)
 
/*
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  function OSY_WVB		C-version 1.00	851124
C	    OSY_RVB                       1.00	851124
C  K. Banse			ESO - Garching
C  !!		Modifed 900626  for elementary i/o mode (FO)
C  source code on file OSYWVB.C
C
C.KEYWORDS
C  virtual blocks on disk
C
C.PURPOSE
C  write, read virtual blocks from disk
C
C.ALGORITHM
C  use system service QIOW 
C  !!! this code is operating system dependant !!!
C
C.INPUT/OUTPUT
C  use as  status = OSY_WVB(iochan,pbuf,nobyt,vbn)
C           	    OSY_RVB(iochan,pbuf,nobyt,vbn)
C
C  input par:
C  IOCHAN:	int		I/O channel assigned to disk file
C  PBUF:	char pointer 	pointer to buffer for disk transfer
C  NOBYT:	int		no. of bytes to be transferred
C  VBN:		int		starting virtual block for data transfer
C 
C  return value:
C  STATUS:	int		return status
C
C--------------------------------------------------
C
*/
	
int   iochan,nobyt,vbn;
char  *pbuf;
 
{
int   bytes;

char	block[512];
	



if (iochan < 0)			/* memory frame */
   {
   int idx;

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

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



/* Write only multiple of 512 bytes ...	*/

status = SS$_NORMAL;
bytes = nobyt & (~511);
if (bytes) 
   {
   status = SYS$QIOW(0,iochan,IO$_WRITEVBLK,iosb,0,0,pbuf,bytes,vbn,0,0,0);
   pbuf += bytes;
   }


/* Write remaining part ...	*/

bytes = nobyt & (511);
if ((status & BIT_0) && bytes)
   {
   int i;

   vbn += nobyt>>9;
   status = SYS$QIOW(0,iochan,IO$_READVBLK,iosb,0,0,block,512,vbn,0,0,0);
   for (i=0; i<bytes; i++)	
      block[i] = pbuf[i];

   if (status & BIT_0) 
      status = SYS$QIOW(0,iochan,IO$_WRITEVBLK,iosb,0,0,block,512,vbn,0,0,0);
   }

if (status & BIT_0) 
   status = ERR_NORMAL;
else
   {
   MID_ERROR("'OSY","OSY_WVB/QIOW",status,0);
   status = ERR_INPINV;
   }

return status;
}

/*

*/

int OSY_RVB(iochan,pbuf,nobyt,vbn)
int   iochan, nobyt, vbn;
char *pbuf;                      	/* pointer to data buffer */
 
{
int   even_bytes;
	
 

if (iochan < 0)                 /* memory frame */
   {
   int idx;

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

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


/* make sure, we have an even no. of bytes */
 
even_bytes = nobyt + (nobyt % 2);
status = SYS$QIOW(0,iochan,IO$_READVBLK,iosb,0,0,pbuf,even_bytes,vbn,0,0,0);
 
if (status & BIT_0) 
   status = ERR_NORMAL;
else
   {
   MID_ERROR("OSY","OSY_RVB/QIOW",status,0);	
   status = ERR_INPINV;
   }

return status;
}

/*

*/

int OSY_WRCHAN(iochan,cbuf,len)
 
/*
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  function OSY_WRCHAN		C-version 1.00	860616
C  K. Banse			ESO - Garching
C
C.KEYWORDS
C  virtual blocks on disk
C
C.PURPOSE
C  write, read virtual blocks from disk
C
C.ALGORITHM
C  use system service QIOW 
C  !!! this code is operating system dependant !!!
C
C.INPUT/OUTPUT
C  use as  STATUS = OSY_WRCHAN(IOCHAN,CBUF,LEN)
C
C  input par:
C  IOCHAN:	int		I/O channel assigned to disk file
C  CBUF:	char pointer	pointer to be written/read
C  LEN:		int		length of char buffer CBUF points to
C  
C  for OSY_RDCHAN only:
C  PROMPT:	char pointer	pointer to prompt buffer
C  PLEN:	int		length of prompt buffer PROMPT points to
C				if = 0, no prompting required
C  output par:
C  COUNT:	int 		no. of values read (OSY_RDCHAN only)
C 
C  return value:
C  STATUS:	int		return status
C
C.VERSIONS
C--------------------------------------------------
C
*/
	
int   iochan, len;
char	*cbuf;
 
{
 
status = SYS$QIOW(0,iochan,IO$_WRITEVBLK,iosb,0,0,cbuf,len,0,0,0,0);

if (status & BIT_0) 
   status = ERR_NORMAL;
else
   {
   MID_ERROR("'OSY","OSY_WRCHAN/QIOW",status,0);
   status = ERR_INPINV;
   }

return status;
}

