/* @(#)ose.c	19.1 (ES0-DMD) 02/25/03 13:56:11 */
/*===========================================================================
  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
===========================================================================*/

/*++++++++++++
.TYPE        Module
.NAME        ose
.LANGUAGE    C
.AUTHOR      IPG-ESO Garching (B. Pirenne)
.CATEGORY    Host operating system interfaces. Interprocess event flags
.COMMENTS    
      These routines will handle the interprocess events flags.
      They will allow the following :
          * prepare a process to receive information in event flags
          * set an event flag among the process group
          * clear an event flag among the process group
          * read the state of an event flag
          * wait for an event flag to be set.
.VERSION  0.0 	29-Jan-1987   Definition      B. Pirenne, D. Ponz, P.
	       Linde
.VERSION  1.0	30-Jan-1987   Programmation   B. Pirenne
.REMARKS  VMS / UNIX SYSV + BSD Version 
----------*/

#include <errno.h>
#include <osparms.h>
#include <osdefos.h>
/* MID_EXTERN int oserror;    (defined in osparms.h.  tm04.09.89) */

#if MID_OS_VMS
#	include <ssdef.h>
	extern int vmserror;
#else	
	static  unsigned char *flag = NULL_PTR(unsigned char);
#endif

#if (!MID_OS_VMS)
/*===================================================================*/
int oseprep()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE prepare the event flags in a newly created process.
.METHOD  Simply gets the shared memory address and put it into the
	character pointer "flag" defined in <osparms.h>.
.RETURNS Upon successful completion a value of zero is returned, else -1
         is returned and ``oserror'' is set to the actual error code.
.REMARKS System dependencies:
 -- UNIX: osmshget(0)
.REMARKS This service is best run as the first statement of a process.
-----------*/
{
  flag = (unsigned char *)osmalloc(_NFLAGS);
  if (flag)	oscfill(flag, _NFLAGS, 0);
  return(oserror ? -1 : 0);
}
#endif

/*===================================================================*/
int oseset(eid)
/*+++++++
.PURPOSE sets a flag (flag is set among all the processes)
.RETURNS Value 0 on normal return. 
.METHOD  1. Check if the flag number is good
.METHOD  2. Set the flag.
.REMARKS 
------------------------------------------------------------*/
	int eid;  /* IN : identification of the flag to set */
{
	register int i;

  if (eid <= 0 || eid > _NFLAGS) 
	oserror = EINVAL;
  else
  {	
#if MID_OS_VMS
	vmserror = SYS$SETEF(eid);
	oserror = (vmserror&1 ? 0 : EINTR);
#else
  	i = eid-1, oserror = 0;
	if (!flag)	oseprep();
	*(flag + i) = 1;
#endif
  }

  return(oserror ? -1 : 0);
}

/*===================================================================*/
int oseclear(eid)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE clears a flag (flag is cleared among all the processes)
.RETURNS Value 0 on normal return. 
.METHOD  1. Check if the flag number is good
.METHOD  2. Clear the given flag.
.REMARKS 
------------------------------------------------------------*/
	int eid;	/* IN : identification of the flag to clear */
{
	register int i;

  if (eid <= 0 || eid > _NFLAGS) 
	oserror = EINVAL;
  else
  {	
#if MID_OS_VMS
	vmserror = SYS$CLREF(eid);
	oserror = (vmserror&1 ? 0 : EINTR);
#else
  	i = eid-1, oserror = 0;
	if (!flag)	oseprep();
	*(flag + i) = 0;
#endif
  }

  return(oserror ? -1 : 0);
}

/*===================================================================*/
int oseread(eid)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE check the state of a flag.
.RETURNS The value of the flag (0  or  1) or -1 in the signal number was
   not valid.
.REMARKS 
------------------------------------------------------------*/
	int eid;	/* IN : identification of the flag to check */
{
	int ret;

  if (eid <= 0 || eid > _NFLAGS) 
	oserror = EINVAL;
  else
  {	
#if MID_OS_VMS
	vmserror = SYS$READEF(eid, &ret);
	oserror = (vmserror&1 ? 0 : EINTR);
#else
	ret = eid-1, oserror = 0;
	if (!flag)	oseprep();
	ret = *(flag + ret);
#endif
  }
  return(oserror ? -1 : ret);
}

/*===================================================================*/
int osewait(eid)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Waits for a flag to be received
.RETURNS returns always 0.
.METHOD  loop until the flag eid is set. The loop pauses for one second between
         each new check.
.REMARKS 
------------------------------------------------------------*/
	int eid;	/* IN : event flag identification */
{
#if MID_OS_VMS
  if (eid <= 0 || eid > _NFLAGS) 
	oserror = EINVAL;
  else  vmserror = SYS$WAITFR(eid), oserror = (vmserror&1 ? 0 : EINTR);
#else
  while (oseread(eid) == 0) 
        ospwait(1);
#endif

  return(oserror ? -1 : 0);
}
