/* @(#)aglvms.c	19.1 (ES0-DMD) 02/25/03 13:53:06 */
/*===========================================================================
  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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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
===========================================================================*/

/* @(#)aglvms.c	19.1  (OAA-ASTRONET) 02/25/03 13:53:06   */
/*
 * HEADER : aglvms.c       - Vers 3.6.000  - Dec 1991 -  L. Fini, OAA
 */


#define MIN(x,y) ((x)<(y))?(x):(y)

/*****************************************************************************/
/* Environment dependent features are resolved in this file                  */


#define AUXLNG 257
#define SS$_NORMAL 1

/*****************************************************************************/
/*                       AGL_trns (Internal AGL use)                         */
/*                             VAX/VMS version                               */

/* This VMS version uses VMS logical names translation                       */

/* Translates logical names until no further translation is possible         */
/* NOTE: Equivalence name is also forced to lower case and colon is stripped */
/*       off                                                                 */

void AGL_trns(inpname,maxlng,trnslnam)
 char *inpname;                           /* Input name                      */
 int  maxlng;                             /* Max output string length        */
 char *trnslnam;                          /* Output equivalence name         */
 {
  struct dsc$descriptor trnam,wrk;        /* Define CHARACTER descriptors    */
  char auxbuf[AUXLNG];
  extern long LIB$SYS_TRNLOG();
  long retstat;
  int cnt;
  short retlng;
  char *src, *dst;

  trnam.dsc$b_class=1;
  trnam.dsc$w_length=maxlng-1;
  trnam.dsc$a_pointer=trnslnam;
  wrk.dsc$b_class=1;
  wrk.dsc$a_pointer=auxbuf;

  retlng=MIN(strlen(inpname),AUXLNG);
  for(cnt=0; cnt<=retlng; cnt++) auxbuf[cnt] = TOUPPER(inpname[cnt]);
  wrk.dsc$w_length=retlng;

  do                                          /* Translation loop            */
   {
    retstat=LIB$SYS_TRNLOG(&wrk,&retlng,&trnam,NULL,NULL,NULL);
    cnt=0; src=trnslnam; dst=auxbuf;
    while(retlng--)
     {
      if(isgraph(*src)) { *dst++ = TOLOWER(*src); cnt++; }
      src++;
     }
    wrk.dsc$w_length=cnt;
   }
  while(retstat==SS$_NORMAL);

  src=auxbuf;
  while( *src == '_' ) { cnt--; src++; }    /* strip off leading underscores */
  strncpy(trnslnam,src,cnt);
  src = trnslnam+cnt;
  *(src)='\0'; src--;                       /* null terminate                */

  if(*src == ':') *src = '\0';              /* Drop the terminating colon */
 }


int AGL_spawn(cmd)
char *cmd;
{
struct dsc$descriptor wrk;            /* Define CHARACTER descriptors    */
extern long LIB$SPAWN();
long retstat;

wrk.dsc$b_class=1;
wrk.dsc$a_pointer=cmd;
wrk.dsc$w_length = strlen(cmd);
retstat = LIB$SPAWN(&wrk,NULL,NULL,NULL,NULL,
                      NULL,NULL,NULL,NULL,NULL,NULL,NULL);
if(retstat != SS$_NORMAL) 
	return (-1);
return 0;
}


/*  Terminal I/O emulator for VAX/VMS                                        */

/*  This module is required due to the fact that VAX-C runtime library       */
/*  doesn't support ioctl. It provides fopen,fclose,fread,fwrite emulated by */
/*  VMS System Service calls, in PASSTRHOUGH mode so that it works as usual  */
/*  Unix calls in RAWMODE. Ioctl is substituted by a dummy entry             */


#define IO$M_NOECHO 	0x0040
#define IO$M_NOFILTR 	0x0200
#define IO$_READVBLK 	0x31
#define IO$_TTYREADALL  0x3A
#define IO$_WRITEVBLK 	0x30
#define IO$M_PURGE      0x0800
#define IO$M_NOFORMAT   0x0100
#define SS$NORMAL       1
#define ERROR           (-1)

#define RFUNCT (IO$_READVBLK | IO$M_NOECHO | IO$_TTYREADALL)
#define RFLUSH (IO$_READVBLK | IO$M_NOECHO | IO$_TTYREADALL | IO$M_PURGE)
#define WFUNCT (IO$_WRITEVBLK | IO$M_NOFORMAT )

static short chan[10]=     /* This is an internal buffer for I/O.          */
                      { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };

static int rfunct=RFLUSH;      /* Read function. with flush the first time */

/***************************************************************************/
/*                               AGL_fopen                                  */

/* This routine is used to open an i/o channel to a terminal. It must take */
/* into account system specific details. E.g. VMS systems will always open */
/* an I/O channel to be used for subsequent SYS$QIO calls, whereas Unix    */
/* systems will probably simply issue a standard fopen call.               */

FILE *AGL_fopen (name)

char * name;                  /* Device name (if it is tt, unix and MS-DOS  */
                              /* systems will simply return stdout). VMS    */
                              /* systems will open SYS$OUTPUT               */
{
 int status; 
 static char *sysout = "SYS$OUTPUT";
  long  SYS$ASSIGN();

 struct dsc$descriptor_s descr;
 char *device;
 int i;

 for(i=0;i<10;i++)
  {                           /* Search a free slot    */
   if(chan[i]==(-1)) break;
  }
 if(i==10) return(NULL);

 if(strcmp(name,"tt")==0)
  {
   descr.dsc$w_length = strlen (sysout);
   descr.dsc$a_pointer = sysout;
  }
 else
  {
   descr.dsc$w_length = strlen (name);
   descr.dsc$a_pointer = name;
  }
 descr.dsc$b_class = DSC$K_CLASS_S;           /* string class                */
 descr.dsc$b_dtype = DSC$K_DTYPE_T;           /* ascii type                  */

 status = SYS$ASSIGN (&descr,&chan+i,0,0);    /* Assign the channel          */

 if(status != SS$NORMAL)
  {
   chan[i]=(-1);
   return (NULL);
  }

 return ((FILE *)(chan+i));
}


/*****************************************************************************/
/*                               AGL_fread                                    */
/*****************************************************************************/

int AGL_fread (buffer,size,nbytes,dev) 

char *buffer;                  /* Output buffer                              */
int size;                      /* Dummy argument. Must be equal to 1         */
int  nbytes;                   /* Number of characters to read               */
FILE *dev;                     /* pointer to VMS I/O channel                 */
{
 double iosb;
 int status;
 short *intchan;

 intchan = (short*)dev;

 status = SYS$QIOW(1,*intchan,rfunct,&iosb, 0,0,buffer,nbytes,0,0,0,0);

 rfunct = RFUNCT;                  /* Avoid flushing next time you read      */

 if (status != SS$NORMAL) return (ERROR);

 return (nbytes);           /* WARNING!! IT IS NOT POSSIBLE  TO RETURN THE 
                                           NUMBER OF BYTES ACTUALLY READ     */
}

/*****************************************************************************/
/*                               AGL_fwrite                                   */
/*****************************************************************************/

int AGL_fwrite (buffer,size,nbytes,dev) 
char *buffer;                  /* Input buffer                               */
int size;                      /* Dummy argument. Must be equal to 1         */
int  nbytes;                   /* Number of characters to write              */
FILE *dev;                     /* pointer to VMS I/O channel                 */
{
 double iosb;
 int status,funct;
 short *intchan;

 intchan = (short*)dev;
 funct = WFUNCT;
 status = SYS$QIOW(1,*intchan,funct,&iosb,0,0,buffer,nbytes,0,0,0,0);

 if (status != SS$NORMAL) return (ERROR);

 return (nbytes); 
}



/*****************************************************************************/
/*                               AGL_fclose                                   */
/*****************************************************************************/

int AGL_fclose (dev)
FILE *dev;                      /*  FILE pointer (obtained via AGL_fopen)    */
{
int status;
short *intchan;
long  SYS$DASSGN();

intchan = (short*)dev;
 
if(*intchan==(-1)) 
	return(-1);

status = SYS$DASSGN (*intchan);
 
if (status != SS$NORMAL) return (-1);
 
*intchan=(-1);
return (0);
}



/***************************************************************************/
/*                      AGL_setraw  AGL_reset                                */

/* These are dummy routines. The terminal I/O is performed in RAW mode     */
/* anyway on VMS systems                                                   */

int AGL_setraw (filept)
 FILE * filept;
 {
 }

void AGL_reset(filept)
 FILE * filept;
  {
  }

int AGL_fflush (filept)
 FILE * filept;
 {
  rfunct=RFLUSH;               /* Preset flushing on next read             */
 }

