340 lines
8.3 KiB
C
340 lines
8.3 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)
|
|
{
|
|
strlcpy(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)
|
|
{
|
|
SConnection *pCon;
|
|
char pBueffel[80];
|
|
|
|
assert(pUser);
|
|
|
|
pCon = (SConnection *) pUser;
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "status = %s", pText[(int) eCode]);
|
|
SCWrite(pCon, pBueffel, eLog);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------- The CallBack function for interest ------------------*/
|
|
static int StatusHDBCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
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,
|
|
VALUECHANGE, StatusCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
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,
|
|
VALUECHANGE, StatusHDBCallback,
|
|
node, NULL);
|
|
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 */
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "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());
|
|
SCsetMacro(pCon, 0);
|
|
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->sockHandle < 0) {
|
|
SCWrite(pCon,
|
|
"GOTCHA!!! Control still lives! You CANNOT grab it! FUCK OFF",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* now the wizardry */
|
|
pOwner->sockHandle = pCon->sockHandle;
|
|
return 1;
|
|
}
|