347 lines
10 KiB
C
347 lines
10 KiB
C
/*--------------------------------------------------------------------------
|
|
|
|
Just a Status management object. Not very exciting.
|
|
|
|
|
|
Mark Koennecke, November 1996
|
|
added callback facilities and interst command.
|
|
Mark Koennecke, August 1997
|
|
|
|
Updated in order to prevent status floods
|
|
Mark Koennecke, July 2004
|
|
|
|
Reworked restore to keep parameters from uninitialized devices
|
|
Mark Koennecke, November 2007
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
-----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include <string.h>
|
|
#include "sics.h"
|
|
#include "status.h"
|
|
#include "interrupt.h"
|
|
#include "sicshipadaba.h"
|
|
#undef VALUECHANGE
|
|
#define VALUECHANGE 2
|
|
|
|
|
|
static char *pText[] = {
|
|
"Eager to execute commands",
|
|
"User requested Wait",
|
|
"Counting",
|
|
"No Beam",
|
|
"Paused",
|
|
"Driving",
|
|
"Running",
|
|
"Running a scan",
|
|
"Writing data",
|
|
"Processing a batch file",
|
|
"Halted",
|
|
"Dead",
|
|
"Waiting for User Input",
|
|
"Counting/Driving",
|
|
"Working",
|
|
NULL };
|
|
|
|
static char *iText[] = {
|
|
"eager",
|
|
"userwait",
|
|
"count",
|
|
"nobeam",
|
|
"paused",
|
|
"driving",
|
|
"running",
|
|
"scanning",
|
|
"writing",
|
|
"batch",
|
|
"halt",
|
|
"dead",
|
|
"input",
|
|
"count/drive",
|
|
"working",
|
|
NULL };
|
|
|
|
static pICallBack pCall = NULL;
|
|
static int fixed = 0;
|
|
static Status eCode = eEager;
|
|
/*-------------------------------------------------------------------------*/
|
|
void KillStatus(void *pData)
|
|
{
|
|
if(pCall != NULL)
|
|
{
|
|
DeleteCallBackInterface(pCall);
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void SetStatus(Status eNew)
|
|
{
|
|
if(!fixed)
|
|
{
|
|
if(eCode == eNew)
|
|
{
|
|
return;
|
|
}
|
|
eCode = eNew;
|
|
InvokeCallBack(pCall,VALUECHANGE,NULL);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
void SetStatusFixed(Status eNew)
|
|
{
|
|
if(eCode == eNew)
|
|
{
|
|
return;
|
|
}
|
|
eCode = eNew;
|
|
InvokeCallBack(pCall,VALUECHANGE,NULL);
|
|
fixed = 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
void ClearFixedStatus(Status eNew)
|
|
{
|
|
if(eCode == eNew)
|
|
{
|
|
return;
|
|
}
|
|
eCode = eNew;
|
|
InvokeCallBack(pCall,VALUECHANGE,NULL);
|
|
fixed = 0;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
Status GetStatus(void)
|
|
{
|
|
return eCode;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void GetStatusText(char *buf, int iBufLen)
|
|
{
|
|
strncpy(buf,pText[(int)eCode],iBufLen-1);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SetStatusFromText(char *text)
|
|
{
|
|
int i = 0;
|
|
|
|
/* check for short form */
|
|
strtolower(text);
|
|
while(iText[i] != NULL)
|
|
{
|
|
if(strcmp(text,iText[i]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if(i >= 10)
|
|
{
|
|
/* check for long form */
|
|
i = 0;
|
|
while(pText[i] != NULL)
|
|
{
|
|
if(strcmp(text,pText[i]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if(i >= 10)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
SetStatus((Status)i);
|
|
return 1;
|
|
}
|
|
/*------------------- The CallBack function for interest ------------------*/
|
|
static int StatusCallback(int iEvent, void *pEvent, void *pUser,
|
|
commandContext cc)
|
|
{
|
|
SConnection *pCon;
|
|
char pBueffel[80];
|
|
|
|
assert(pUser);
|
|
|
|
pCon = (SConnection *)pUser;
|
|
|
|
sprintf(pBueffel,"status = %s", pText[(int)eCode]);
|
|
SCPushContext2(pCon,cc);
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
SCPopContext(pCon);
|
|
return 1;
|
|
}
|
|
/*------------------- The CallBack function for interest ------------------*/
|
|
static int StatusHDBCallback(int iEvent, void *pEvent, void *pUser,
|
|
commandContext cc)
|
|
{
|
|
pHdb node = NULL;
|
|
hdbValue v;
|
|
|
|
assert(pUser);
|
|
|
|
node = (pHdb)pUser;
|
|
v = MakeHdbText(pText[eCode]);
|
|
if(node != NULL && iEvent == VALUECHANGE){
|
|
UpdateHipadabaPar(node,v,NULL);
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int UserStatus(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
char pBueffel[512];
|
|
long lID;
|
|
pHdb node = NULL;
|
|
|
|
assert(pSics);
|
|
assert(pCon);
|
|
|
|
/* create callback if not present */
|
|
if(pCall == NULL)
|
|
{
|
|
pCall = CreateCallBackInterface();
|
|
}
|
|
|
|
/* check for interest */
|
|
if(argc > 1)
|
|
{
|
|
strtolower(argv[1]);
|
|
if(strcmp(argv[1],"interest") == 0)
|
|
{
|
|
lID = RegisterCallback(pCall, SCGetContext(pCon),
|
|
VALUECHANGE, StatusCallback,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, pCall,lID);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"hdbinterest") == 0)
|
|
{
|
|
if(argc > 2){
|
|
node = GetHipadabaNode(GetHipadabaRoot(),argv[2]);
|
|
if(node != NULL){
|
|
lID = RegisterCallback(pCall, SCGetContext(pCon),
|
|
VALUECHANGE, StatusHDBCallback,
|
|
node, NULL);
|
|
/* SCRegister(pCon,pSics, pCall,lID); */
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
SCWrite(pCon,"ERROR: Hipadaba node not found",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
} else {
|
|
SCWrite(pCon,"ERROR: require node parameter to register status callback",
|
|
eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* else just print value */
|
|
sprintf(pBueffel,"status = %s", pText[(int)eCode]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int ResetStatus(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
SCWrite(pCon,"Insufficient authorisation to reset server",eError);
|
|
return 0;
|
|
}
|
|
SetStatus(eEager);
|
|
SetInterrupt(eContinue);
|
|
ClearExecutor(GetExecutor());
|
|
return 1;
|
|
}
|
|
/* ===================== Control Connection Management ====================*/
|
|
static SConnection *pOwner = NULL;
|
|
|
|
void SetControl(SConnection *pCon)
|
|
{
|
|
pOwner = pCon;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int IsControl(SConnection *pCon)
|
|
{
|
|
if(pCon == pOwner)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SConnection *GetControl(void)
|
|
{
|
|
return pOwner;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int RedirectControl(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* check user Rights */
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
SCWrite(pCon,
|
|
"You have NO, I repeat NO, Privilege to grab a control connection",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* check if the connection is dead at all */
|
|
if(pCon->pSock)
|
|
{
|
|
SCWrite(pCon,
|
|
"GOTCHA!!! Control still lives! You CANNOT grab it! FUCK OFF",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* now the wizardry */
|
|
pOwner->pSock = pCon->pSock;
|
|
return 1;
|
|
}
|