/*===========================================================================
  Copyright (C) 1995-2010 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 MIDKEY +++++++++++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION  Module MIDKEY
.AUTHOR   Klaus Banse           ESO - Garching
.KEYWORDS Midas keyword utility routines.
.ENVIRONMENT VMS and UNIX
.COMMENT  
 holds FNDKEY, MOVKEY, TYPCHK, GETLOCAL

.VERSION 
 100222		last modif	

------------------------------------------------------------------------*/
 
#include <fileexts.h>
#include <fsydef.h>
#include <stdio.h>
#include <stdlib.h>

#if vms
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif 
 
#define  READ         0
#define  WRITE        1
#define  READ_WRITE   2
#define  APPEND       3
 
#define MAX_LEVEL  25           /* synchronize with midback.h ...*/


static struct KEY_STRUCT  *keypntr;

static char   level[MAX_LEVEL+4] = "ABCDEFGHIJKLMNOPQRSTUVWXY";
			/* synchronize with MID_DEFKEY + CLEAR_LOCAL... */

static char cdif = 'A' - 'a';
 
/*

*/

int MID_FNDKEY(name,type,bytelm,noelm,unit)
 
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  find the entry of a given keyword + return related info, if found
.ALGORITHM
  first search IDENT[0 - 14] for matching name + level (in IDENT[16])
  equal current procedure (i.e. treat as local key);
  if not found search as global key
  the current procedure level is stored (as integer) in keyword MODE(7)
  global keys are stored bottom-up, local keys top-down...
.RETURN
  kentry:	I*4		no. of entry, if found;	-1, if not found
-----------------------------------------------------------------------------*/
 
char   *name	/* IN : name of keyword  */;
char   *type	/* OUT: type of keyword, 
			currently I,R,C,D,S are recognized for
                        I*4,R*4,CHAR*n,R*8, size_t  */;
int   *bytelm	/* OUT: no. of bytes per element of keyword data */;
int   *noelm	/* OUT: no. of elements connected to keyword */;
int   *unit	/* OUT: pointer to units-pointer  */;
 
{
int  kstrn, proglevel;
register int  nr;

char    loclevel, kname[20];
register char  nc;




for (nr=0; nr<=KEY_NAMELEN; nr++)
   {
   nc = name[nr];
   if (nc == '\0')
      {
      kstrn = nr;
      goto step_a;
      }
   if ((nc >= 'a') && (nc <= 'z'))		/* convert to upper case */
      nc += cdif;
   kname[nr] = nc;
   }
return (-1);					/* bad (too long) keyname */


step_a:
if (kstrn < KEY_NAMELEN) kname[kstrn++] = ' ';	/* append a blank */

proglevel = KIWORDS[OFF_MODE+6] - 1;		/* get procedure level */
if (proglevel >= 0)
   {	
 
   /* first loop through LOCNAMES from KEYALL.LOCENT till KEYALL.LOCNO
   and compare the key names as well as the levels                    */

   keypntr = KEYALL.KEYNAMES + KEYALL.LOCNO;
   loclevel = level[proglevel];

   for (nr=KEYALL.LOCNO; nr>=KEYALL.GLOBENT; nr--)
      {
      if ( (keypntr->IDENT[16] >= loclevel) &&
           (strncmp(keypntr->IDENT,kname,(size_t)kstrn) == 0) ) goto gotcha;

      keypntr --;
      }
   }

 
/* then also loop through GLOBNAMES from 0 till KEYALL.GLOBNO  */
 
keypntr = KEYALL.KEYNAMES;			/* restart at beginning */
for (nr=0; nr<=KEYALL.GLOBNO; nr++)	/* KEYALL.GLOBNO is last entry used */
   {
   if (strncmp(keypntr->IDENT,kname,(size_t)kstrn) == 0)
      goto gotcha;

   keypntr ++;
   }
 
/*  arriving here means, that we didn't find it */
 
return (-1);
 
gotcha:
*type = keypntr->IDENT[15];
*bytelm = keypntr->BYTELEM;
*noelm = keypntr->NOELEM;
*unit = 0;				/* not used currently */

return nr;				/* keyword found */
}
/*

*/

void MID_TYPCHK(intype,outtype,bytelm)

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  check given data type + return cleaned type and no. of bytes per element
.ALGORITHM
  straight forward
.RETURNS nothing.
---------------------------------------------------------------------------*/

char  *intype;	/* IN : type of keyword/descr */
char  *outtype;	/* OUT: type of keyword/descr currently I,R,C,D,S
                        set to ' ', if invalid INTYPE given */
int  *bytelm;	/* OUT: no. of bytes per element of keyword/descr data */
 
{
int  mm, lbytlm;

register char   test;



*outtype = ' ';					/* default to no_success ... */

test = *intype;
if ((test >= 'a') && (test <= 'z'))		/* convert to upper case */
   test += cdif;

	
/*  first look for type CHAR*len */
 
if (test == 'C') 
   {
   mm = CGN_INDEXC(intype,'*');		/* search for '*' */
   if (mm < 0 ) 
      {
      *bytelm = 1;			/* that is o.k. */
      *outtype = 'C';
      }
   else
      {					/* point to char. following '*' */
      lbytlm = -1;
      lbytlm = atoi(intype+mm+1);
      if ( lbytlm > 0) 
         {
         *bytelm = lbytlm;
	 *outtype = 'C';		/* only o.k., if valid number */
         }
      }
   }

	
/*  then for integer, real + double precision */
 
else if (test == 'I') 
   {
   *bytelm = II_SIZE;
   *outtype = 'I';
   }

else if (test == 'R') 
   {					/* distinguish between R*4 and R*8 */
   if ( CGN_INDEXS(intype,"*8") > 0) 
      {
      *bytelm = DD_SIZE;
      *outtype = 'D';
      }
   else
      {
      *bytelm = RR_SIZE;
      *outtype = 'R';
      }
   }

else if (test == 'D') 
   {
   *bytelm = DD_SIZE;
   *outtype = 'D';
   }

else if (test == 'S') 
   {
   *bytelm = SS_SIZE;
   *outtype = 'S';
   }
}	
/*

*/

void MID_GETLOCAL(inoutno,keyid,byti,noi)

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  loop through local keys + return type and no. of bytes per element
.ALGORITHM
  straight forward
.RETURNS nothing.
---------------------------------------------------------------------------*/

int   *inoutno;		/* IN/OUT: = 0 to start search, > 0 to continue (IN),
				     n on return for nth local key (n > 0),
				    -1 on return if no more local keyw. */
char  *keyid;		/* OUT: keyname in [0] - [14]
				type    in [15]
				level   in [16]  */
int   *byti;		/* OUT: no. of bytes per elem */
int   *noi;		/* OUT: no. of elements of key */

{
register int  nr;
int   proglevel;
static int  localcount;

static struct KEY_STRUCT  *lkeypntr;

static char  kbloclevel;




if (*inoutno == 0) 			/* start of search for local keys */
   {
   proglevel = KIWORDS[OFF_MODE+6] - 1;         /* get procedure level */
   if (proglevel >= 0)
      {
      /* loop through LOCNAMES from KEYALL.LOCENT till KEYALL.LOCNO
         and get all local keynames */

      kbloclevel = level[proglevel];
      lkeypntr = KEYALL.KEYNAMES + KEYALL.LOCNO;
      localcount = 0;
      for (nr=KEYALL.LOCNO; nr>=KEYALL.GLOBENT; nr--)
         {
         if (lkeypntr->IDENT[16] >= kbloclevel) goto gotcha;

         lkeypntr --;
         }
      }
   }
else
   {
   if (lkeypntr >= KEYALL.KEYNAMES + KEYALL.GLOBENT) 
      {
      lkeypntr --;
      if (lkeypntr->IDENT[16] >= kbloclevel) goto gotcha;
      }
   }
*inoutno = -1;
return;


gotcha:
localcount ++;
*inoutno = localcount;
(void) strncpy(keyid,lkeypntr->IDENT,17);
*byti = lkeypntr->BYTELEM;
*noi = lkeypntr->NOELEM;
}
/*

*/
 
#if vms
 
int MID_MOVKEY(direc,option)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  initialize the system keywords from binary file FORGRxy.KEY
  or write keywords to that file
.ALGORITHM
  either use par. 'option' as keyfile name or build name
.RETURNS
  status:      I*4		return status
--------------------------------------------------*/
char    *direc	   /* IN: [0] = direction of moving, I or O \
                          [1] = M(onitor) or X(tension) or A(pplication) */;
char    *option    /* IN: if not blank, it's already the name of the keyfile */;
 
{
static int  initflg = -1;
static int  gp;

int  ksz, dsz, totsize, keysize, datsize;
int  ggp, status, n, mm;

char    *tmpntr; 
char    buf[4], work[200], *cpntr;
 
struct KEY_STRUCT  *keyname;



totsize = sizeof(struct KEY_ALL);
 


/* --------------------------------*/
/*  move keywords in               */
/* --------------------------------*/

if (*direc++ == 'I')				/* already move to direc[1] */
   {
   initflg ++;
   ggp = -1;


   /* if Midas from Unix command line => DAZUNIT is not defined */

   if (*direc == 'A')
      {
      ksz = 0;          /* MIDAS application */
      OSY_GETSYMB("DAZUNIT",buf,4);
      if ((buf[0] == 'D') && (buf[1] == 'A') && (buf[2] == 'Z'))
         {
         (void) strcpy(work,"FORGRdrs.KEY");
         ggp = 0;
         ksz += 10;
         }
      else
         {
         (void) OSY_TRNLOG("MID_WORK",work,168,&mm);
         if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND;
         (void) strcpy(&work[mm],"FORGR  .KEY");
         work[mm+5] = buf[0];
         work[mm+6] = buf[1];
         }
      }
   else
      {
      ksz = 1;          /* MIDAS monitor */
      if (*option == ' ')		/* use default keyword file */
         {
         (void) OSY_TRNLOG("MID_WORK",work,168,&mm);
         if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND;
         (void) strcpy(&work[mm],"FORGR  .KEY");
         OSY_GETSYMB("DAZUNIT",buf,4);
         work[mm+5] = buf[0];
         work[mm+6] = buf[1];
         }
      else if (*option == '*')		/* use fixed (for Unix) keyword file */
         {
         (void) strcpy(work,"FORGRdrs.KEY");
         ggp = 0;
         ksz += 10;
         }
      else
         (void) strcpy(work,option);
      }
 
   keyname = KEYALL.KEYNAMES;		/* save pointers in case of need */
   KDWORDS = KEYALL.KEYWORDS;

   gp = osdopen(work,READ_WRITE);

   if (gp == -1)
      {		
      if (ggp == 0)
         {				/* get FORGRdrs.KEY from MID_MONIT */
         (void) OSY_TRNLOG("MID_MONIT",work,156,&mm);
         if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND;
         (void) strcpy(&work[mm],"FORGRdrs.KEY");
         ggp = osdopen(work,READ);
         if (ggp == -1)
            {                        /* we can't use MID_ERROR yet...  */
            (void) printf("Could not open keyfile %s \n\r",work);
            return ERR_KEYBAD;
            }
         gp = ggp;
         }
      else
         {
         (void) printf("Could not open keyfile %s \n\r",work);
         return ERR_KEYBAD;
         } 
      }
   else
      ggp = -1;				/* avoid using ggp */

 
/*  read binary keyfile via 3 osdread's  */

   cpntr = (char *) &KEYALL;
   status = osdread(gp,cpntr,(unsigned int)totsize);
   if (status < totsize) goto osd_rerror;
   /*
   printf("totsize = %d\n",totsize);
   */


   keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
   datsize = KEYALL.LOCDAT + 2;		/* synchronize with midasgo.c */
   KEYALL.ORIGIN = ksz;                 /* 0 (applic) or 1 (monitor) */


/*  now also check, if we extend the keyword area */

   if (*direc == 'X')
      {
      n = KIWORDS[OFF_MONPAR+2];		/* new no. of global keys */
      mm  = KIWORDS[OFF_MONPAR+3];		/* new no. of local keys */
      KEYALL.GLOBENT = n;
      KEYALL.GLOBDAT = KEYALL.GLOBENT * KEY_FACT;
      KEYALL.LOCENT = n + mm;
      KEYALL.LOCDAT = KEYALL.LOCENT * KEY_FACT;
      KEYALL.LOCNO = KEYALL.GLOBENT  - 1;	/* reset local keywords */
      KEYALL.LOCEND = KEYALL.GLOBDAT  - 1;
      ksz = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
      dsz = KEYALL.LOCDAT + 2;

      cpntr = (char *) KEYALL.KEYNAMES;		/* release previous memory */
      free(cpntr);
      cpntr = (char *) KEYALL.KEYWORDS;
      free(cpntr);
      initflg = 0;				/* enforce memory allocation */
      }
   else
      {
      ksz = keysize;
      dsz = datsize;
      }

   if (initflg == 0)
      {
      tmpntr = malloc((size_t)ksz);
      if (tmpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_names\n",ksz);
         ospexit(0);
         }
      memset(tmpntr,0,ksz);
      KEYALL.KEYNAMES = (struct KEY_STRUCT *) tmpntr;

      tmpntr = malloc((size_t)dsz);
      if (tmpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_data\n",dsz);
         ospexit(0);
         }
      memset(tmpntr,0,dsz);
      KEYALL.KEYWORDS = (double *) tmpntr;
      }
   else if ((KEYALL.ORIGIN == 1) || (KEYALL.ORIGIN == 11))
      {					 /* for monitor reuse old pointers */
      KEYALL.KEYNAMES = keyname;
      KEYALL.KEYWORDS = KDWORDS;
      }

   status = osdread(gp,(char *) KEYALL.KEYNAMES,(unsigned int)keysize);
   if (status < keysize) goto osd_rerror;


   status = osdread(gp,(char *) KEYALL.KEYWORDS,(unsigned int)datsize);
   if (status < datsize) goto osd_rerror;
   /*
   printf("keysize = %d, "datsize = %d\n",keysize,datsize);
   */

   if (ggp > -1)
      {					/* we must create local FORGRdrs.KEY */
      (void) osdclose(ggp);
      gp = osdopen("FORGRdrs.KEY",WRITE);
      if (gp == -1)
         {                              /* we can't use MID_ERROR yet...  */
         (void) printf("Could not create local keyfile FORGRdrs.KEY\n\r");
         return ERR_KEYBAD;
         }
      }


/*  initialize the data pointers */

   KDWORDS = KEYALL.KEYWORDS;
   KIWORDS = (int *) KEYALL.KEYWORDS;
   KRWORDS = (float *) KEYALL.KEYWORDS;
   KCWORDS = (char *) KEYALL.KEYWORDS;
   }
 
 
/* --------------------------------*/
/*  move keywords out              */
/* --------------------------------*/

else	
   {
   status = osdseek(gp,(off_t)0,FILE_START);          /* rewind file */

   cpntr = (char *) &KEYALL;
   status = osdwrite(gp,cpntr,(unsigned int)totsize);
   if (status < totsize) goto osd_werror;

   keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
   cpntr = (char *) KEYALL.KEYNAMES;
   status = osdwrite(gp,cpntr,(unsigned int)keysize);
   if (status < keysize) goto osd_werror;

   datsize = KEYALL.LOCDAT + 2;
   cpntr = (char *) KEYALL.KEYWORDS;
   status = osdwrite(gp,cpntr,(unsigned int)datsize);
   if (status < datsize) goto osd_werror;
 
   status = osdclose(gp);
   }
 
			/*  normal end   */
return ERR_NORMAL;

osd_rerror:
(void) printf("MID_MOVKEY - Problems reading keyfile: %s \n\r",work);
osdclose(gp);
if (KEYALL.ORIGIN > 9)
   ospexit(ERR_KEYBAD);
else
   return ERR_KEYBAD;

osd_werror:
status = ERR_KEYBAD;                   /* here we can use MID_ERROR...  */
MID_ERROR("MIDAS","MID_MOVKEY",status,0);
osdclose(gp);
return status;
}

#else

/*

*/
 
/* here the Linux/Unix version */

int MID_MOVKEY(direc,option)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  initialize the system keywords from binary file FORGRxy.KEY
  or write keywords to that file
.ALGORITHM
  either use par. 'option' as keyfile name or build name
.RETURNS
  status:      I*4		return status
--------------------------------------------------*/
char    *direc	   /* IN: [0] = direction of moving, I or O \
                          [1] = M(onitor) or X(tension) or A(pplication) */;
char    *option    /* IN: if not blank, it's already the name of the keyfile
			  if "*" or "**" it's an outside job */;
 
{
static int  initflg = -1;
static int  gp;

int  ksz, dsz, totsize, keysize, datsize;
int  status, n, mm;

char    *tmpntr; 
char    buf[4], work[200], *cpntr;
 
struct KEY_STRUCT  *keyname;



totsize = sizeof(struct KEY_ALL);
 


/* --------------------------------*/
/*  move keywords in               */
/* --------------------------------*/

if (*direc++ == 'I')				/* already move to direc[1] */
   {
   initflg ++;
   if (*direc == 'A') 
      ksz = 0;					/* MIDAS application */
   else
      ksz = 1;					/* MIDAS monitor */

   keyname = KEYALL.KEYNAMES;		/* save pointers in case of need */
   KDWORDS = KEYALL.KEYWORDS;

   /* work will hold the relevant keyword file name */

   (void) OSY_TRNLOG("MID_WORK",work,168,&mm);
   if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND;

   if (*option == ' ')			/* use default keyword file */
      {
      (void) memcpy(&work[mm],"FORGR  .KEY",(size_t)12);
      OSY_GETSYMB("DAZUNIT",buf,4);
      work[mm+5] = buf[0];
      work[mm+6] = buf[1];
      }
 
   else if (*option != '*')		/* use passed keyword file */
      (void) strcpy(work,option);
      
   else				
      {
      ksz += 10;
      (void) memcpy(work,"FORGRdrs.KEY",(size_t)13);
      option++;				/* check next char. */
      if (*option != '*')		/* overwrite any FORGdrs.KEY */
         {
         gp = -1;
         goto test_gp;			/* avoid opening of file */
         }
      }
 
   gp = osdopen(work,READ_WRITE);

  test_gp:
   if (gp == -1)
      {		
      if (ksz >= 10)
         {				/* get FORGRdrs.KEY from MID_MONIT */
         char  cmd[240], cmm[160];

         (void) OSY_TRNLOG("MID_MONIT",cmm,156,&mm);
         if (strncmp("MID_MONIT",cmm,mm) == 0)
            {                              /* we can't use MID_ERROR yet... */
            (void) printf("variable MID_MONIT is not defined...\n");

            gp = osdopen("FORGRdrs.KEY",READ_WRITE);
            if (gp == -1)
               {         
               (void) printf
                  ("also, no existing keyfile here - we give up...\n");
               return ERR_KEYBAD;
               }
            goto keyfile_ok;
            }

         if (cmm[mm-1] != FSY_DIREND) cmm[mm++] = FSY_DIREND;
         (void) memcpy(&cmm[mm],"FORGRdrs.KEY",(size_t)13);

         (void) strcpy(cmd,"cp ");      /* build up command to copy keyfile */
         (void) strcpy(&cmd[3],cmm);    /* from MID_MONIT to here */
         (void) strcat(cmd," FORGRdrs.KEY");

         status = system(cmd);             /* let HostSyS do the copying */
         if (status != 0)
            {                              /* we can't use MID_ERROR yet... */
            (void) printf
              ("System could not copy FORGRdrs.KEY from MID_MONIT to here\n");
            return ERR_KEYBAD;
            }

         gp = osdopen(work,READ_WRITE);
         if (gp == -1)
            {                        /* we can't use MID_ERROR yet...  */
            (void) printf("Could not open keyfile %s \n",work);
            return ERR_KEYBAD;
            }
         }

      else
         {
         (void) printf("Could not open keyfile %s \n",work);
         return ERR_KEYBAD;
         } 
      }

 
/*  read binary keyfile via 3 osdread's  */

keyfile_ok:
   cpntr = (char *) &KEYALL;
   status = osdread(gp,cpntr,(unsigned int)totsize);
   if (status < totsize) goto osd_rerror;
   				/* printf("totsize = %d\n",totsize); */


   keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
   datsize = KEYALL.LOCDAT + 2;		/* synchronize with midasgo.c */
   KEYALL.ORIGIN = ksz;                 /* 0 (applic) or 1 (monitor) */


/*  now also check, if we extend the keyword area */

   if (*direc == 'X')
      {
      n = KIWORDS[OFF_MONPAR+2];		/* new no. of global keys */
      mm  = KIWORDS[OFF_MONPAR+3];		/* new no. of local keys */
      KEYALL.GLOBENT = n;
      KEYALL.GLOBDAT = KEYALL.GLOBENT * KEY_FACT;
      KEYALL.LOCENT = n + mm;
      KEYALL.LOCDAT = KEYALL.LOCENT * KEY_FACT;
      KEYALL.LOCNO = KEYALL.GLOBENT  - 1;	/* reset local keywords */
      KEYALL.LOCEND = KEYALL.GLOBDAT  - 1;
      ksz = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
      dsz = KEYALL.LOCDAT + 2;

      cpntr = (char *) KEYALL.KEYNAMES;		/* release previous memory */
      free(cpntr);
      cpntr = (char *) KEYALL.KEYWORDS;
      free(cpntr);
      initflg = 0;				/* enforce memory allocation */
      }
   else
      {
      ksz = keysize;
      dsz = datsize;
      }

   if (initflg == 0)
      {
      tmpntr = malloc((size_t)ksz);
      if (tmpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_names\n",ksz);
         ospexit(0);
         }
      memset(tmpntr,0,ksz);
      KEYALL.KEYNAMES = (struct KEY_STRUCT *) tmpntr;

      tmpntr = malloc((size_t)dsz);
      if (tmpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_data\n",dsz);
         ospexit(0);
         }
      memset(tmpntr,0,dsz);
      KEYALL.KEYWORDS = (double *) tmpntr;
      }
   else if ((KEYALL.ORIGIN == 1) || (KEYALL.ORIGIN == 11))
      {					 /* for monitor reuse old pointers */
      KEYALL.KEYNAMES = keyname;
      KEYALL.KEYWORDS = KDWORDS;
      }

   status = osdread(gp,(char *) KEYALL.KEYNAMES,(unsigned int)keysize);
   if (status < keysize) goto osd_rerror;


   status = osdread(gp,(char *) KEYALL.KEYWORDS,(unsigned int)datsize);
   if (status < datsize) goto osd_rerror;
   /*
   printf("keysize = %d, "datsize = %d\n",keysize,datsize);
   */


/*  initialize the data pointers */

   KDWORDS = KEYALL.KEYWORDS;
   KSWORDS = (size_t *) KEYALL.KEYWORDS;
   KIWORDS = (int *) KEYALL.KEYWORDS;
   KRWORDS = (float *) KEYALL.KEYWORDS;
   KCWORDS = (char *) KEYALL.KEYWORDS;
   }
 
 
/* --------------------------------*/
/*  move keywords out              */
/* --------------------------------*/

else	
   {
   status = osdseek(gp,(off_t)0,FILE_START);          /* rewind file */

   cpntr = (char *) &KEYALL;
   status = osdwrite(gp,cpntr,(unsigned int)totsize);
   if (status < totsize) goto osd_werror;

   keysize = sizeof(struct KEY_STRUCT) * (KEYALL.LOCENT+1);
   cpntr = (char *) KEYALL.KEYNAMES;
   status = osdwrite(gp,cpntr,(unsigned int)keysize);
   if (status < keysize) goto osd_werror;

   datsize = KEYALL.LOCDAT + 2;
   cpntr = (char *) KEYALL.KEYWORDS;
   status = osdwrite(gp,cpntr,(unsigned int)datsize);
   if (status < datsize) goto osd_werror;
 
   status = osdclose(gp);
   }
 
			/*  normal end   */
return ERR_NORMAL;

osd_rerror:
(void) printf("MID_MOVKEY - Problems reading keyfile: %s \n\r",work);
osdclose(gp);
(void) printf("did you execute once \"Midas> @ ascii_bin\" after Midas installation?\n\r");
if (KEYALL.ORIGIN > 9)
   ospexit(ERR_KEYBAD);
else
   return ERR_KEYBAD;

osd_werror:
status = ERR_KEYBAD;                   /* here we can use MID_ERROR...  */
MID_ERROR("MIDAS","MID_MOVKEY",status,0);
osdclose(gp);
return status;
}

#endif

/*

*/
 
/* here the Linux/Unix version using mmap, munmap
 *
 * which we abandon for now (060505)
 * since it gives problems on some systems, e.g.
 *
 *      HP-Compaq laptop with RedHat,
 *      Pentium with Scientific Linux 4.2
 *
 */

#if Klaus-is-retired

int MID_MOVKEY(direc,option)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  initialize the system keywords from binary file FORGRxy.KEY
  or write keywords to that file
.ALGORITHM
  either use par. 'option' as keyfile name or build name
.RETURNS
  status:      I*4		return status
--------------------------------------------------*/
char    *direc	   /* IN: [0] = direction of moving, I or O \
                          [1] = M(onitor) or X(tension) or A(pplication) */;
char    *option    /* IN: if not blank, it's already the name of the keyfile */;
 
{
int  whoami, keysize, datsize;
int  status, n, mm;
static int  initflg = -1;
static int  gp;
static int  szkeytotal, szkeyall, szkeynam, szkeydat;

char    action1, action2, buf[4], work[200], *cpntr, *tmpntr;
static char  *mapbuf;
 
double  *keywords;

struct stat statbuf;

void *mapadr;




szkeyall = (int) sizeof(struct KEY_ALL);
action1 = *direc++;			/* already move to direc[1] */


/* --------------------------------*/
/*  move keywords in               */
/* --------------------------------*/

if (action1 == 'I')	
   {
   initflg ++;

   whoami = 1;				/* default to MIDAS monitor */
   action2 = *direc;
   if (action2 == 'A') whoami = 0;	/* it's a MIDAS application */

   (void) OSY_TRNLOG("MID_WORK",work,168,&mm);
   if (work[mm-1] != FSY_DIREND) work[mm++] = FSY_DIREND;
 
   if (*option == ' ')			/* use default keyword file */
      {
      (void) memcpy(&work[mm],"FORGR  .KEY",(size_t)12);
      OSY_GETSYMB("DAZUNIT",buf,4);
      work[mm+5] = buf[0];
      work[mm+6] = buf[1];
      }

   else if (*option != '*')		/* use passed keyword file */
      (void) strcpy(work,option);
   

   /* for outside-Midas-work, option = '*'  and we use FORGRdrs.KEY */

   else
      {
      whoami += 10;

      (void) memcpy(&work[mm],"FORGRdrs.KEY",(size_t)13);
      gp = open(work,O_RDWR);
      if (gp >= 0) 
         goto get_file_info;
      else
         {		/* copy FORGRdrs.KEY from MID_MONIT to MID_WORK */
         char  cmd[400], wwork[200];

         (void) OSY_TRNLOG("MID_MONIT",wwork,156,&mm);
         if (wwork[mm-1] != FSY_DIREND) wwork[mm++] = FSY_DIREND;
         (void) memcpy(&wwork[mm],"FORGRdrs.KEY",(size_t)13);

         (void) strcpy(cmd,"cp ");	/* build up command to copy keyfile */
         (void) strcpy(&cmd[3],wwork);	/* from MID_MONIT to MID_WORK */
         (void) strcat(cmd," ");
         (void) strcat(cmd,work);

         status = system(cmd);		/* let HostSyS do the copying */
         if (status != 0)
            {				/* we can't use MID_ERROR yet... */
            (void) printf
               ("Could not copy FORGRdrs.KEY from MID_MONIT to MID_WORK dir");
            return ERR_KEYBAD;
            }
         }
      }


  map_open:			/* come back here, if keywords extension! */
   gp = open(work,O_RDWR);		/* open file for read/write */
   if (gp == -1)			/* open failed ... */
      {		
      (void) printf("Could not open keyfile %s \n",work);
      return ERR_KEYBAD;
      }


   /* whoami = 0/10 (applic) or 1/11 (monitor) */
 
  get_file_info:
   keywords = KEYALL.KEYWORDS; 		/* save pointer in case of need */

   status = fstat(gp,&statbuf);		/* get all info about file */
   if (status != 0)
      {
      (void) printf("Could not fstat keyfile %s \n",work);
      return ERR_KEYBAD;
      }
   szkeytotal = statbuf.st_size;	/* total file size in bytes */

   mapadr = 0;
   mapbuf = (char *) mmap(mapadr,(size_t)szkeytotal,PROT_READ | PROT_WRITE,
                          MAP_SHARED,gp,(off_t)0); 
   if (mapbuf == (char *) (-1))		/* that's MAP_FAILED */
      {
      close (gp);
      (void) printf("Could not mmap keyfile %s \n",work);
      return ERR_KEYBAD;
      }

   cpntr = (char *) &KEYALL;
   (void) memcpy(cpntr,mapbuf,(size_t)szkeyall);

   keysize = (int) sizeof(struct KEY_STRUCT)*(KEYALL.LOCENT+1);
   datsize = KEYALL.LOCDAT + 2;		/* synchronize with midasgo.c!! */

   KEYALL.ORIGIN = whoami;		/* do not use the one just copied */
					/* from mapbuf ... */

   /*  now also check, if we extend the keyword area */

   if (action2 == 'X')		/* here only, if we are the Monitor ... */
      {			
      int  ksz, dsz;

      n = KIWORDS[OFF_MONPAR+2];		/* new no. of global keys */
      mm  = KIWORDS[OFF_MONPAR+3];		/* new no. of local keys */

      munmap(mapbuf,(size_t)szkeytotal);	/* unmap + close keyfile */
      close(gp);				/* we just opened */
      tmpntr = (char *) KEYALL.KEYWORDS;
      free(tmpntr);
 
      /* now open keyfile as binary file + read "old" KEYALL structure */

      gp = osdopen(work,READ_WRITE);
      if (gp == -1) 
         {
         (void) printf("MID_MOVKEY + osdopen => we should NOT come here!!!\n");
         ospexit(1);
         }
      status = osdread(gp,(char *) &KEYALL,(unsigned int)szkeyall);
      if (status < szkeyall) goto osd_rerror;

      KEYALL.GLOBENT = n;			/* update KEYALL structure */
      KEYALL.GLOBDAT = KEYALL.GLOBENT * KEY_FACT;
      KEYALL.LOCENT = n + mm;
      KEYALL.LOCDAT = KEYALL.LOCENT * KEY_FACT;
      KEYALL.LOCNO = KEYALL.GLOBENT  - 1;	/* reset local keywords */
      KEYALL.LOCEND = KEYALL.GLOBDAT  - 1;

      ksz = (int) sizeof(struct KEY_STRUCT)*(KEYALL.LOCENT+1);
      dsz = KEYALL.LOCDAT + 2;			/* new sizes */

      cpntr = malloc((size_t)ksz);	/* aligned to char */
      if (cpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_names\n",ksz);
         if (*option == '*') 
            {
            SCTSYS(M_BLUE_COLOR,
                   "maybe an old, incompatible FORGRdrs.KEY file in MID_WORK?");
            SCTSYS(M_BLUE_COLOR,
                 "copy a platform compatible FORGRdrs.KEY from MID_MONIT to MID_WORK.");
            }
         ospexit(0);
         }

      tmpntr = malloc((size_t)dsz);	/* will be aligned to double */
      if (tmpntr == NULL)
         {
         (void) printf("could not allocate %d bytes for key_data\n",dsz);
         if (*option == '*') 
            {
            SCTSYS(M_BLUE_COLOR,
                   "maybe an old, incompatible FORGRdrs.KEY file in MID_WORK?");
            SCTSYS(M_BLUE_COLOR,
                 "copy a platform compatible FORGRdrs.KEY from MID_MONIT to MID_WORK.");
            }
         ospexit(0);
         }
      KEYALL.KEYWORDS = (double *) tmpntr;

      /* now read KEYNAMES + KEYWORDS into new larger buffers */

      status = osdread(gp,cpntr,(unsigned int)keysize);
      if (status < keysize) goto osd_rerror;
      status = osdread(gp,(char *) KEYALL.KEYWORDS,(unsigned int)datsize);
      if (status < datsize) goto osd_rerror;

      /* and write the larger buffers out - thus increasing the file size */

      status = osdseek(gp,(off_t)0,FILE_START);          /* rewind file */
      status = osdwrite(gp,(char *) &KEYALL,(unsigned int)szkeyall);
      if (status < szkeyall) goto osd_werror;
      status = osdwrite(gp,cpntr,(unsigned int)ksz);
      if (status < ksz) goto osd_werror;
      status = osdwrite(gp,(char *) KEYALL.KEYWORDS,(unsigned int)dsz);
      if (status < dsz) goto osd_werror;
      status = osdclose(gp);
      free(cpntr);		/* we don't need KEYNAMES buffer anymore */

      /* now we use the new, larger keyfile and do again the mapping */
     
      action2 = 'M';
      goto map_open;
      }



   if (initflg == 0)		/* here also as an application ... */
      {
      tmpntr = malloc((size_t)datsize);	/* will be aligned to double */
      if (tmpntr == NULL)
         {
         (void) 
         printf("could not allocate %d bytes for key_data\n",datsize);
         if (*option == '*') 
            {
            SCTSYS(M_BLUE_COLOR,
                   "maybe an old, incompatible FORGRdrs.KEY file in MID_WORK?");
            SCTSYS(M_BLUE_COLOR,
                 "copy a platform compatible FORGRdrs.KEY from MID_MONIT to MID_WORK.");
            }
         ospexit(0);
         }
      KEYALL.KEYWORDS = (double *) tmpntr;
      }

   else if ((KEYALL.ORIGIN == 1) || (KEYALL.ORIGIN == 11))
      {					 /* for monitor reuse old pointers */
      KEYALL.KEYWORDS = keywords;
      }

   KEYALL.KEYNAMES = (struct KEY_STRUCT *) (mapbuf + szkeyall);

   szkeynam = keysize;
   szkeydat = datsize;

   cpntr = (char *) KEYALL.KEYWORDS;
   (void) memcpy(cpntr,mapbuf+szkeyall+szkeynam,(size_t)datsize);

   KDWORDS = KEYALL.KEYWORDS;		/*  initialize the data pointers */
   KIWORDS = (int *) KEYALL.KEYWORDS;
   KRWORDS = (float *) KEYALL.KEYWORDS;
   KCWORDS = (char *) KEYALL.KEYWORDS;
   }
 
 
/* --------------------------------*/
/*  move keywords out              */
/* --------------------------------*/

else	
   {
   cpntr = (char *) &KEYALL;
   (void) memcpy(mapbuf,cpntr,(size_t)szkeyall);
   cpntr = (char *) KEYALL.KEYWORDS;
   (void) memcpy(mapbuf+szkeyall+szkeynam,cpntr,(size_t)szkeydat);

   n = szkeyall + szkeynam + szkeydat;
   if (n > szkeytotal)
      {
      printf("OJO:  szkeyall+szkeynam+szkeydat (= %d) > szkeytotal (= %d)\n",
             n,szkeytotal);
      return ERR_KEYBAD;
      }

   status = munmap(mapbuf,(size_t)szkeytotal);
   if (status != 0)
      {
      (void) printf("munmap failed...\n");
      }
   close(gp);
   }
 
			/*  normal end   */
return ERR_NORMAL;

osd_rerror:
(void) printf("MID_MOVKEY - Problems reading keyfile: %s \n",work);
goto closing;
osd_werror:
(void) printf("MID_MOVKEY - Problems writing keyfile: %s \n",work);

closing:
osdclose(gp);
if (KEYALL.ORIGIN > 9)
   ospexit(ERR_KEYBAD);
else
   return ERR_KEYBAD;
}

#endif

