4445 lines
117 KiB
C
4445 lines
117 KiB
C
/**
|
|
* This is a set of helper functions for SICS to work with the hierarchical parameter
|
|
* database hipadaba. In SICS, the calldata associated with any callback will always
|
|
* be the connection object.
|
|
*
|
|
* copyright: GPL
|
|
*
|
|
* Mark Koennecke, June 2006
|
|
*
|
|
* Introduced notification on tree changes, Mark Koennecke, November 2006
|
|
*
|
|
* Added property functions, Mark Koennecke, January 2007
|
|
*
|
|
* Added hmatchprop function. Mark Koennecke, February 2008
|
|
*
|
|
* TODO: separate this into two modules: sicshipadaba proper and sicshipadabaint for the
|
|
* interpreter interface.
|
|
*
|
|
* Refactored to new callback system, Markus Zolliker, Mark Koennecke, March 2008
|
|
*
|
|
* Added start and finished messages to commands. Mark Koennecke, November 2008
|
|
*
|
|
* Added SicsValueCheckCallback and implemented first version of haddcheck.
|
|
* Mark Koennecke, July 2013
|
|
*
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <sicshipadaba.h>
|
|
#include <sicshdbadapter.h>
|
|
#include "sicspoll.h"
|
|
#include <lld.h>
|
|
#include <stptok.h>
|
|
#include "protocol.h"
|
|
#include "statusfile.h"
|
|
#include <splitter.h>
|
|
#include "sicsobj.h"
|
|
#include <macro.h>
|
|
#include "arrayutil.h"
|
|
#include "HistMem.h"
|
|
#include "asynnet.h"
|
|
#include <json-c/json.h>
|
|
|
|
#define MAX_HDB_PATH 1024
|
|
|
|
/*== there can be only one hipadaba in SICS, some globals to care for that == */
|
|
static pHdb root = NULL;
|
|
static pSicsPoll poller = NULL;
|
|
typedef enum {
|
|
normal_protocol,
|
|
json_protocol,
|
|
} Protocol;
|
|
char *trim(char *str);
|
|
/*====================== Messages ==================================================*/
|
|
static char killID[] = { "killID" };
|
|
static char killInternalID[] = { "killInternalID" };
|
|
static char killPtr[] = { "killPtr" };
|
|
static char startID[] = { "start" };
|
|
static char stopID[] = { "stop" };
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
pHdbIDMessage GetKillIDMessage(pHdbMessage message)
|
|
{
|
|
if (message->type == killID) {
|
|
return (pHdbIDMessage) message;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
pHdbIDMessage GetKillInternalIDMessage(pHdbMessage message)
|
|
{
|
|
if (message->type == killInternalID) {
|
|
return (pHdbIDMessage) message;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
pHdbPtrMessage GetKillPtrMessage(pHdbMessage message)
|
|
{
|
|
if (message->type == killPtr) {
|
|
return (pHdbPtrMessage) message;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
pHdbMessage GetHdbStartMessage(pHdbMessage message)
|
|
{
|
|
if (message->type == startID) {
|
|
return (pHdbMessage) message;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
pHdbMessage GetHdbStopMessage(pHdbMessage message)
|
|
{
|
|
if (message->type == stopID) {
|
|
return (pHdbMessage) message;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------*/
|
|
void SendHdbStatusMessage(pHdb node, char *status)
|
|
{
|
|
pHdbMessage pRes = NULL;
|
|
pRes = malloc(sizeof(hdbMessage));
|
|
if (pRes == NULL) {
|
|
return;
|
|
}
|
|
if (strcmp(status, "start") == 0) {
|
|
pRes->type = startID;
|
|
} else if (strcmp(status, "stop") == 0) {
|
|
pRes->type = stopID;
|
|
} else {
|
|
/* someone is trying to create an non existent message */
|
|
assert(0);
|
|
}
|
|
InvokeCallbackChain(node, pRes);
|
|
free(pRes);
|
|
}
|
|
|
|
/*=============== common callback functions used for SICS ===========================*/
|
|
static hdbCallbackReturn SICSCheckPermissionCallback(pHdb node,
|
|
void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
int *testPriv = NULL;
|
|
SConnection *pCon = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
testPriv = (int *) userData;
|
|
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
/*
|
|
* If pCon is NULL, then this is an internal call from some driver
|
|
* code where no permission check is necessary. However, when called
|
|
* through the hipadaba tree commands and other upper level code, the
|
|
* check will be honoured.
|
|
*/
|
|
if (pCon == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
assert(testPriv != NULL);
|
|
|
|
if (SCMatchRights(pCon, *testPriv) == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeCheckPermissionCallback(int priv)
|
|
{
|
|
int *testPriv = NULL;
|
|
|
|
testPriv = malloc(sizeof(int));
|
|
if (testPriv == NULL) {
|
|
return NULL;
|
|
}
|
|
*testPriv = priv;
|
|
return MakeHipadabaCallback(SICSCheckPermissionCallback, testPriv, free);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static char *removeSetUpdateID = "removeSetUpdate";
|
|
|
|
void RemoveSetUpdateCallback(pHdb node)
|
|
{
|
|
hdbPtrMessage m;
|
|
|
|
m.type = killPtr;
|
|
m.pPtr = removeSetUpdateID;
|
|
InvokeCallbackChain(node, (pHdbMessage) & m);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSSetUpdateCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdbDataMessage mm = NULL;
|
|
pHdbPtrMessage pm = NULL;
|
|
int status;
|
|
|
|
pm = GetKillPtrMessage(message);
|
|
if (pm != NULL) {
|
|
if (pm->pPtr == removeSetUpdateID) {
|
|
return hdbKill;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
status = UpdateHipadabaPar(node, *(mm->v), mm->callData);
|
|
if (status && mm->callData != NULL) {
|
|
SCSendOK(mm->callData);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSetUpdateCallback()
|
|
{
|
|
return MakeHipadabaCallback(SICSSetUpdateCallback, NULL, NULL);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSReadOnlyCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
if (pCon != NULL) {
|
|
SCWrite(pCon, "ERROR: parameter is READ-ONLY", eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeReadOnlyCallback()
|
|
{
|
|
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL, NULL);
|
|
}
|
|
/*------------------------------------------------------------------------------------*/
|
|
hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
char values[1024], *pPtr, pToken[80], *pVal;
|
|
int status;
|
|
hdbValue v;
|
|
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = (SConnection *) mm->callData;
|
|
v = *(mm->v);
|
|
|
|
status = GetHdbProperty(node,"values",values,sizeof(values));
|
|
if(status != 1 && pCon != NULL){
|
|
SCPrintf(pCon,eLogError,"ERROR: configuration error, no values on node %s",
|
|
node->name);
|
|
return hdbAbort;
|
|
}
|
|
|
|
if(v.dataType != HIPTEXT && pCon != NULL){
|
|
SCPrintf(pCon,eLogError,"ERROR: need text data for node %s",
|
|
node->name);
|
|
return hdbAbort;
|
|
}
|
|
|
|
pPtr = values;
|
|
pVal = strdup(v.v.text);
|
|
strtolower(pVal);
|
|
while((pPtr = stptok(pPtr,pToken,sizeof(pToken),",")) != NULL){
|
|
if(strcmp(pToken,pVal) == 0) {
|
|
free(pVal);
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
free(pVal);
|
|
|
|
if(pCon != NULL){
|
|
SCPrintf(pCon,eLogError,"ERROR: %s not allowed as value for %s, allowed are: %s",
|
|
v.v.text, node->name, values);
|
|
}
|
|
|
|
return hdbAbort;
|
|
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSDriveCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pDummy dum = NULL;
|
|
char pSicsdev[80];
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
hdbValue v;
|
|
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
pCon = (SConnection *) mm->callData;
|
|
v = *(mm->v);
|
|
|
|
dum = (pDummy) userData;
|
|
assert(pCon != NULL && dum != NULL);
|
|
if (GetHdbProperty(node, "sicsdev", pSicsdev, 79)) {
|
|
status = StartDevice(pServ->pExecutor, pSicsdev, dum->pDescriptor,
|
|
userData, pCon, RUNDRIVE, (float) v.v.doubleValue);
|
|
} else {
|
|
status = StartDevice(pServ->pExecutor, node->name, dum->pDescriptor,
|
|
userData, pCon, SCGetRunLevel(pCon), (float) v.v.doubleValue);
|
|
}
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSDriveCallback(void *sicsObject)
|
|
{
|
|
return MakeHipadabaCallback(SICSDriveCallback, sicsObject, NULL);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSReadDriveCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
static SConnection *defCon = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDummy dum = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
float value;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
mm = GetHdbGetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
pCon = (SConnection *) mm->callData;
|
|
dum = (pDummy) userData;
|
|
assert(dum != NULL);
|
|
|
|
if (defCon == NULL) {
|
|
defCon = SCCreateDummyConnection(pServ->pSics);
|
|
}
|
|
|
|
pDriv = dum->pDescriptor->GetInterface(dum, DRIVEID);
|
|
assert(pDriv != NULL);
|
|
if (pCon != NULL) {
|
|
value = pDriv->GetValue(dum, pCon);
|
|
node->value.v.doubleValue = (double) value;
|
|
mm->v->v.doubleValue = (double) value;
|
|
} else {
|
|
if (defCon != NULL) {
|
|
value = pDriv->GetValue(dum, defCon);
|
|
node->value.v.doubleValue = (double) value;
|
|
mm->v->v.doubleValue = (double) value;
|
|
}
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSFuncCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdb par[64], current = NULL;
|
|
int nPar = 0;
|
|
SICSOBJFunc func = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
int status;
|
|
|
|
mm = GetHdbSetMessage(message);
|
|
if (mm == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
assert(node->value.dataType == HIPFUNC);
|
|
if (userData == NULL || mm->callData == NULL) {
|
|
printf("Great Badness in calling SICSFuncCallback\n");
|
|
return hdbAbort;
|
|
}
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
par[nPar] = current;
|
|
nPar++;
|
|
current = current->next;
|
|
}
|
|
func = (SICSOBJFunc) node->value.v.func;
|
|
if (func != NULL) {
|
|
SendHdbStatusMessage(node, "start");
|
|
status = func((pSICSOBJ) userData, (SConnection *) mm->callData,
|
|
node, par, nPar);
|
|
SendHdbStatusMessage(node, "stop");
|
|
} else {
|
|
printf("Great Badness in calling SICSFuncCallback\n");
|
|
return hdbAbort;
|
|
}
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSFuncCallback(void *obj)
|
|
{
|
|
return MakeHipadabaCallback(SICSFuncCallback, obj, NULL);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject)
|
|
{
|
|
return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject, NULL);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
SConnection *pCon;
|
|
int ID;
|
|
int internalID;
|
|
} HdbCBInfo;
|
|
|
|
static Protocol isJSON(SConnection * pCon, int notify)
|
|
{
|
|
char proName[128];
|
|
void *pData;
|
|
|
|
if (notify == 0 && SCinMacro(pCon)) {
|
|
return normal_protocol;
|
|
}
|
|
pData = FindCommandData(pServ->pSics, "protocol", "Protocol");
|
|
ProtocolGet(pCon, pData, proName, 128);
|
|
if (strcmp(proName, "json") == 0)
|
|
return json_protocol;
|
|
else
|
|
return normal_protocol;
|
|
}
|
|
|
|
/* Format a name,value pair according to the given protocol */
|
|
int formatNameValue(Protocol protocol, char *name, char *value,
|
|
pDynString result, int hdtype)
|
|
{
|
|
char *char_arr, *ptr;
|
|
char token[8], ch;
|
|
|
|
switch (protocol) {
|
|
case normal_protocol:
|
|
DynStringCopy(result, name);
|
|
DynStringConcat(result, " = ");
|
|
DynStringConcat(result, value);
|
|
break;
|
|
case json_protocol:
|
|
switch (hdtype) {
|
|
case HIPNONE:
|
|
DynStringCopy(result, "null");
|
|
break;
|
|
case HIPINT:
|
|
case HIPFLOAT:
|
|
DynStringCopy(result, "{\"");
|
|
DynStringConcat(result, name);
|
|
DynStringConcat(result, "\": ");
|
|
DynStringConcat(result, value);
|
|
DynStringConcat(result, "}");
|
|
break;
|
|
case HIPTEXT:
|
|
DynStringCopy(result, "{\"");
|
|
DynStringConcat(result, name);
|
|
DynStringConcat(result, "\": \"");
|
|
ptr = NULL;
|
|
for (ch=*value; ch!=0; ch=*++value) {
|
|
switch (ch) {
|
|
case '"': strcpy(token, "\\\"");
|
|
case '\\': strcpy(token, "\\\\");
|
|
default:
|
|
if (ch > 127 || ch < 32) {
|
|
snprintf(token, sizeof token, "\\u%4.4x", (unsigned char)ch);
|
|
} else {
|
|
if (!ptr) ptr = value;
|
|
continue;
|
|
}
|
|
}
|
|
if (ptr) {
|
|
DynStringConcatBytes(result, ptr, value - ptr);
|
|
}
|
|
DynStringConcat(result, token);
|
|
}
|
|
if (ptr) {
|
|
DynStringConcatBytes(result, ptr, value - ptr);
|
|
}
|
|
DynStringConcat(result, "\"}");
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
char_arr = ptr = strdup(trim(value));
|
|
while (*ptr != '\0') {
|
|
if (isspace(*ptr))
|
|
*ptr = ',';
|
|
ptr++;
|
|
}
|
|
DynStringCopy(result, "{\"");
|
|
DynStringConcat(result, name);
|
|
DynStringConcat(result, "\": [ ");
|
|
DynStringConcat(result, char_arr);
|
|
DynStringConcat(result, " ]}");
|
|
if (char_arr != NULL)
|
|
free(char_arr);
|
|
break;
|
|
}
|
|
}
|
|
return protocol;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static int sendZippedNodeData(pHdb node, hdbValue newValue, SConnection * pCon)
|
|
{
|
|
int i, *iData = NULL, zip = 1;
|
|
char *path = NULL;
|
|
double sum = 0;
|
|
char value[80];
|
|
|
|
path = GetHipadabaPath(node);
|
|
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
|
|
if(strstr(value,"bin") != NULL) {
|
|
zip = 0;
|
|
}
|
|
}
|
|
switch (newValue.dataType) {
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
if (newValue.v.intArray == NULL) {
|
|
free(path);
|
|
return 0;
|
|
}
|
|
iData = (int *) malloc(newValue.arrayLength * sizeof(int));
|
|
if (iData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in sendZippedData", eError);
|
|
free(path);
|
|
return 0;
|
|
}
|
|
memset(iData, 0, newValue.arrayLength * sizeof(int));
|
|
for (i = 0; i < newValue.arrayLength; i++) {
|
|
/* sum += (double)newValue.v.intArray[i]; */
|
|
iData[i] = htonl(newValue.v.intArray[i]);
|
|
}
|
|
if(zip == 1){
|
|
SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int));
|
|
} else {
|
|
SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int));
|
|
}
|
|
free(iData);
|
|
/* printf("Wrote zipped data %s, sum %lf\n", path, sum); */
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
if (newValue.v.floatArray == NULL) {
|
|
free(path);
|
|
return 0;
|
|
}
|
|
iData = (int *) malloc(newValue.arrayLength * sizeof(int));
|
|
if (iData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in sendZippedData", eError);
|
|
free(path);
|
|
return 0;
|
|
}
|
|
memset(iData, 0, newValue.arrayLength * sizeof(int));
|
|
for (i = 0; i < newValue.arrayLength; i++) {
|
|
sum+= newValue.v.floatArray[i];
|
|
iData[i] = htonl((int) (newValue.v.floatArray[i] * 65536.));
|
|
}
|
|
if(zip == 1) {
|
|
SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int));
|
|
/* printf("Wrote zipped data %s, sum %lf\n", path, sum); */
|
|
} else {
|
|
SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int));
|
|
}
|
|
free(iData);
|
|
break;
|
|
default:
|
|
SCPrintf(pCon, eError, "ERROR: zipped writing not supported for this datatype on node %s",
|
|
path);
|
|
free(path);
|
|
return 0;
|
|
}
|
|
free(path);
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
HdbCBInfo *cbInfo = NULL;
|
|
pDynString printedData = NULL;
|
|
pDynString result = NULL;
|
|
char *pPath = NULL;
|
|
Protocol protocol = normal_protocol;
|
|
int outCode, macro, status;
|
|
char value[80];
|
|
pHdbIDMessage idm = NULL;
|
|
pHdbPtrMessage cmm = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
hdbPropertyChange *propm = NULL;
|
|
hdbValue *hvalue;
|
|
SConnection *tstCon;
|
|
char updatePath[1024];
|
|
char *geterror;
|
|
|
|
cbInfo = (HdbCBInfo *) userData;
|
|
|
|
/*
|
|
* handle kills first
|
|
*/
|
|
if ((idm = GetKillIDMessage(message)) != NULL) {
|
|
if (idm->ID == cbInfo->ID) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if ((idm = GetKillInternalIDMessage(message)) != NULL) {
|
|
if (idm->ID == cbInfo->internalID) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if ((cmm = GetKillPtrMessage(message)) != NULL) {
|
|
tstCon = cmm->pPtr;
|
|
if (tstCon != NULL && SCGetIdent(tstCon) == SCGetIdent(cbInfo->pCon)) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* handle start and stop messages
|
|
*/
|
|
if (GetHdbStartMessage(message) != NULL) {
|
|
pPath = GetHipadabaPath(node);
|
|
result = CreateDynString(128, 128);
|
|
DynStringConcat(result, pPath);
|
|
DynStringConcat(result, " STARTED");
|
|
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
|
|
DeleteDynString(result);
|
|
free(pPath);
|
|
return hdbContinue;
|
|
}
|
|
|
|
if (GetHdbStopMessage(message) != NULL) {
|
|
pPath = GetHipadabaPath(node);
|
|
result = CreateDynString(128, 128);
|
|
DynStringConcat(result, pPath);
|
|
DynStringConcat(result, " FINISHED");
|
|
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
|
|
DeleteDynString(result);
|
|
free(pPath);
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*
|
|
* Deal with update and geterror property messages
|
|
*/
|
|
|
|
if ((propm = GetPropertyChangeMessage(message)) != NULL) {
|
|
if (strcmp(propm->key, "geterror") != 0) {
|
|
/* this is a property change of an other property */
|
|
return hdbContinue;
|
|
}
|
|
geterror = propm->value;
|
|
hvalue = &node->value;
|
|
} else if ((mm = GetHdbUpdateMessage(message)) != NULL) {
|
|
geterror = GetHdbProp(node, "geterror");
|
|
hvalue = mm->v;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
|
|
GetHdbPath(node,updatePath,sizeof(updatePath));
|
|
result = CreateDynString(128, 128);
|
|
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
|
|
if (geterror && *geterror) {
|
|
/* send geterror */
|
|
strlcat(updatePath, ".geterror", sizeof updatePath);
|
|
formatNameValue(protocol, updatePath, geterror, result, HIPTEXT);
|
|
SCPureSockWrite(cbInfo->pCon, Dyn2Cstring(result), outCode);
|
|
return hdbContinue;
|
|
} /* else normal notify */
|
|
|
|
/**
|
|
* if transfer = zip always transfer data in zipped form
|
|
*/
|
|
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
|
|
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
|
|
status = sendZippedNodeData(node, *hvalue, cbInfo->pCon);
|
|
DeleteDynString(result);
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if (hvalue->arrayLength <= 400) {
|
|
printedData = formatValue(*hvalue, node);
|
|
if (printedData == NULL || result == NULL) {
|
|
SCWrite(cbInfo->pCon, "ERROR: out of memory formatting data",
|
|
eEvent);
|
|
/*
|
|
* no need to interrupt something because writing data to a client does
|
|
* not work
|
|
*/
|
|
return hdbContinue;
|
|
}
|
|
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
|
|
hvalue->dataType);
|
|
#ifdef SITE_ANSTO
|
|
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
|
#else
|
|
SCPureSockWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
|
#endif
|
|
DeleteDynString(printedData);
|
|
} else {
|
|
formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT);
|
|
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
|
}
|
|
DeleteDynString(result);
|
|
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------------*/
|
|
static void cbKill(void *pData)
|
|
{
|
|
HdbCBInfo *cbInfo = (HdbCBInfo *) pData;
|
|
if (cbInfo == NULL) {
|
|
return;
|
|
}
|
|
if (cbInfo->pCon != NULL) {
|
|
SCDeleteConnection(cbInfo->pCon);
|
|
}
|
|
free(cbInfo);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeNotifyCallback(SConnection * pCon, int id)
|
|
{
|
|
HdbCBInfo *cbInfo = NULL;
|
|
|
|
cbInfo = malloc(sizeof(HdbCBInfo));
|
|
if (cbInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
cbInfo->pCon = SCCopyConnection(pCon);
|
|
if (cbInfo->pCon == NULL) {
|
|
return NULL;
|
|
}
|
|
SCsetMacro(cbInfo->pCon, 0);
|
|
cbInfo->ID = id;
|
|
cbInfo->internalID = -1;
|
|
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo, cbKill);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char *path = NULL;
|
|
char buffer[1024];
|
|
pDynString result = NULL;
|
|
Protocol protocol = normal_protocol;
|
|
pHdbIDMessage idm = NULL;
|
|
pHdbPtrMessage cmm = NULL;
|
|
int outCode;
|
|
pHdbTreeChangeMessage tm = NULL;
|
|
SConnection *tstCon = NULL;
|
|
|
|
HdbCBInfo *cbInfo = (HdbCBInfo *) userData;
|
|
|
|
/*
|
|
* handle kills first
|
|
*/
|
|
if ((idm = GetKillIDMessage(message)) != NULL) {
|
|
if (idm->ID == cbInfo->ID) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if ((idm = GetKillInternalIDMessage(message)) != NULL) {
|
|
if (idm->ID == cbInfo->internalID) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if ((cmm = GetKillPtrMessage(message)) != NULL) {
|
|
tstCon = cmm->pPtr;
|
|
if (tstCon != NULL && SCGetIdent(tstCon) == SCGetIdent(cbInfo->pCon)) {
|
|
return hdbKill;
|
|
} else {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
|
|
if ((tm = GetHdbTreeChangeMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
if (cbInfo != NULL && cbInfo->pCon != NULL) {
|
|
result = CreateDynString(128, 128);
|
|
if (result == NULL) {
|
|
SCWrite(cbInfo->pCon, "ERROR: out of memory in TreeChangeCallback",
|
|
eError);
|
|
return hdbAbort;
|
|
}
|
|
path = GetHipadabaPath(node);
|
|
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
/* formatNameValue(protocol, "treechange", path, result,
|
|
node->value.dataType); */
|
|
formatNameValue(protocol, "treechange", path, result,
|
|
HIPTEXT);
|
|
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
|
DeleteDynString(result);
|
|
free(path);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeTreeChangeCallback(SConnection * pCon, int id)
|
|
{
|
|
HdbCBInfo *cbInfo = NULL;
|
|
|
|
cbInfo = malloc(sizeof(HdbCBInfo));
|
|
if (cbInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
cbInfo->pCon = SCCopyConnection(pCon);
|
|
if (cbInfo->pCon == NULL) {
|
|
return NULL;
|
|
}
|
|
SCsetMacro(cbInfo->pCon, 0);
|
|
cbInfo->ID = id;
|
|
cbInfo->internalID = -1;
|
|
return MakeHipadabaCallback(TreeChangeCallback, cbInfo, cbKill);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSScriptWriteCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char *command = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDynString newVal = NULL;
|
|
char error[1024];
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
command = (char *) userData;
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
assert(command != NULL && pCon != NULL);
|
|
|
|
newVal = formatValue(*(mm->v), node);
|
|
if (newVal == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory setting parameter", eError);
|
|
return hdbAbort;
|
|
}
|
|
|
|
/**
|
|
* prepend command
|
|
*/
|
|
DynStringInsert(newVal, " ", 0);
|
|
DynStringInsert(newVal, command, 0);
|
|
|
|
/*
|
|
* evaluate
|
|
*/
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), GetCharArray(newVal));
|
|
if (status != TCL_OK) {
|
|
snprintf(error, 1023, "ERROR: tcl returned error: %s",
|
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
SCWrite(pCon, error, eError);
|
|
status = 0;
|
|
} else {
|
|
status = 1;
|
|
}
|
|
DeleteDynString(newVal);
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static pHdbCallback MakeSICSWriteScriptCallback(char *script)
|
|
{
|
|
return MakeHipadabaCallback(SICSScriptWriteCallback, strdup(script),
|
|
free);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSScriptReadCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char *command = NULL, *data = NULL, *equal = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDynString newVal = NULL;
|
|
char error[1024];
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbGetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
command = (char *) userData;
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
assert(command != NULL);
|
|
|
|
/*
|
|
* evaluate
|
|
*/
|
|
if (pCon != NULL) {
|
|
MacroPush(pCon);
|
|
}
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), command);
|
|
if (pCon != NULL) {
|
|
MacroPop();
|
|
}
|
|
if (status != TCL_OK) {
|
|
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
|
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
if (pCon != NULL) {
|
|
SCWrite(pCon, error, eError);
|
|
}
|
|
status = 0;
|
|
} else {
|
|
status = 1;
|
|
}
|
|
|
|
/*
|
|
* decode result. This handles both the case of the standard SICS answer
|
|
* something = anything
|
|
* as well as a plain value alone
|
|
*/
|
|
data = (char *) Tcl_GetStringResult(InterpGetTcl(pServ->pSics));
|
|
if (data == NULL) {
|
|
if (pCon != NULL) {
|
|
SCWrite(pCon, "ERROR: no result returned from script", eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
|
|
/*
|
|
* do we need to copy?
|
|
*/
|
|
if (strstr(data, "@@NOCOPY@@") != NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*
|
|
* we need to copy: do it
|
|
*/
|
|
equal = strchr(data, '=');
|
|
if (equal != NULL) {
|
|
data = equal + 1;
|
|
}
|
|
strcpy(error, "ERROR: ");
|
|
status = readHdbValue(&node->value, data, error + 7, 1024 - 7);
|
|
if (status != 1) {
|
|
if (pCon != NULL) {
|
|
SCWrite(pCon, error, eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
static pHdbCallback MakeSICSReadScriptCallback(char *script)
|
|
{
|
|
return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),
|
|
free);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
int min;
|
|
int max;
|
|
} hdbIntRange, *pHdbIntRange;
|
|
/*---------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSIntRangeCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char buffer[256];
|
|
pHdbIntRange range = NULL;
|
|
SConnection *pCon = NULL;
|
|
int status = 1;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
range = (pHdbIntRange) userData;
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
assert(range != NULL);
|
|
|
|
if (mm->v->v.intValue > range->max || mm->v->v.intValue < range->min) {
|
|
status = SICSCBRANGE;
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255,
|
|
"ERROR: %d is not within permitted range: %d to %d",
|
|
(int) mm->v->v.intValue, range->min, range->max);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdbCallback MakeIntRangeCallback(int min, int max)
|
|
{
|
|
pHdbIntRange range = NULL;
|
|
|
|
range = malloc(sizeof(hdbIntRange));
|
|
if (range == NULL) {
|
|
return NULL;
|
|
}
|
|
range->min = min;
|
|
range->max = max;
|
|
return MakeHipadabaCallback(SICSIntRangeCallback, range, free);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
double min;
|
|
double max;
|
|
} hdbFloatRange, *pHdbFloatRange;
|
|
/*---------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSFloatRangeCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char buffer[256];
|
|
pHdbFloatRange range = NULL;
|
|
SConnection *pCon = NULL;
|
|
int status = 1;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
range = (pHdbFloatRange) userData;
|
|
pCon = (SConnection *) mm->callData;
|
|
|
|
assert(range != NULL);
|
|
|
|
if (mm->v->v.doubleValue > range->max
|
|
|| mm->v->v.doubleValue < range->min) {
|
|
status = SICSCBRANGE;
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255,
|
|
"ERROR: %lf is not within permitted range: %lf to %lf",
|
|
mm->v->v.doubleValue, range->min, range->max);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdbCallback MakeFloatRangeCallback(double min, double max)
|
|
{
|
|
pHdbFloatRange range = NULL;
|
|
|
|
range = malloc(sizeof(hdbFloatRange));
|
|
if (range == NULL) {
|
|
return NULL;
|
|
}
|
|
range->min = min;
|
|
range->max = max;
|
|
return MakeHipadabaCallback(SICSFloatRangeCallback, range, free);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn MemGenReadCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbGetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
switch (node->value.dataType) {
|
|
case HIPINT:
|
|
node->value.v.intValue = *(int *) userData;
|
|
break;
|
|
case HIPFLOAT:
|
|
node->value.v.doubleValue = *(double *) userData;
|
|
break;
|
|
case HIPTEXT:
|
|
if (node->value.v.text != NULL) {
|
|
free(node->value.v.text);
|
|
}
|
|
node->value.v.text = strdup((char *) userData);
|
|
break;
|
|
case HIPINTAR:
|
|
memcpy(&node->value.v.intArray, userData,
|
|
node->value.arrayLength * sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
memcpy(&node->value.v.floatArray, userData,
|
|
node->value.arrayLength * sizeof(double));
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemGenReadCallback(void *address)
|
|
{
|
|
return MakeHipadabaCallback(MemGenReadCallback, address, NULL);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn MemGenSetCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
const char *pPtr = NULL;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
|
|
if (mm->v->dataType != node->value.dataType) {
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
switch (node->value.dataType) {
|
|
case HIPINT:
|
|
memcpy(userData, &mm->v->v.intValue, sizeof(int));
|
|
break;
|
|
case HIPFLOAT:
|
|
memcpy(userData, &mm->v->v.doubleValue, sizeof(double));
|
|
break;
|
|
case HIPTEXT:
|
|
/* the use of strlcpy is probably buggy here (M.Z. 15.4.2010) */
|
|
strlcpy((char *) userData, (const char *) mm->v->v.text,
|
|
node->value.arrayLength);
|
|
break;
|
|
case HIPINTAR:
|
|
memcpy(userData, &mm->v->v.intArray,
|
|
node->value.arrayLength * sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
memcpy(userData, &mm->v->v.floatArray,
|
|
node->value.arrayLength * sizeof(double));
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return 0;
|
|
break;
|
|
}
|
|
UpdateHipadabaPar(node, *(mm->v), mm->callData);
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemGenSetCallback(void *address)
|
|
{
|
|
return MakeHipadabaCallback(MemGenSetCallback, address, NULL);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static void killHdbValue(void *pData)
|
|
{
|
|
hdbValue *v = NULL;
|
|
|
|
v = (hdbValue *) pData;
|
|
if (v == NULL) {
|
|
return;
|
|
}
|
|
ReleaseHdbValue(v);
|
|
free(v);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSIntFixedCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
hdbValue *allowed = NULL;
|
|
SConnection *pCon = NULL;
|
|
int i;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
allowed = (hdbValue *) userData;
|
|
pCon = (SConnection *) mm->callData;
|
|
assert(allowed != NULL && allowed->dataType == HIPINTAR);
|
|
for (i = 0; i < allowed->arrayLength; i++) {
|
|
if (mm->v->v.intValue == allowed->v.intArray[i]) {
|
|
return hdbContinue;
|
|
}
|
|
}
|
|
if (pCon != NULL) {
|
|
SCWrite(pCon, "ERROR: value is not in the list of allowed values",
|
|
eError);
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdbCallback MakeIntFixedCallback(int *data, int length)
|
|
{
|
|
pHdbCallback result = NULL;
|
|
hdbValue *v = NULL;
|
|
|
|
v = malloc(sizeof(hdbValue));
|
|
if (v == NULL) {
|
|
return NULL;
|
|
}
|
|
v->dataType = HIPINTAR;
|
|
v->arrayLength = length;
|
|
v->v.intArray = malloc(length * sizeof(int));
|
|
if (v->v.intArray == NULL) {
|
|
return NULL;
|
|
}
|
|
memcpy(v->v.intArray, data, length * sizeof(int));
|
|
return MakeHipadabaCallback(SICSIntFixedCallback, v, killHdbValue);
|
|
}
|
|
|
|
/*============= Parameter Creation ===========================================*/
|
|
pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v)
|
|
{
|
|
pHdb result = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
char pPriv[20];
|
|
|
|
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
copyHdbValue(&v, &result->value);
|
|
|
|
pHcb = MakeCheckPermissionCallback(priv);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeSetUpdateCallback();
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
switch (priv) {
|
|
case 0:
|
|
strcpy(pPriv, "internal");
|
|
break;
|
|
case 1:
|
|
strcpy(pPriv, "manager");
|
|
break;
|
|
case 2:
|
|
strcpy(pPriv, "user");
|
|
break;
|
|
case 3:
|
|
strcpy(pPriv, "spy");
|
|
break;
|
|
}
|
|
SetHdbProperty(result, "priv", pPriv);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType)
|
|
{
|
|
pHdb result = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
|
|
result = MakeHipadabaNode(name, dataType, 0);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
pHcb = MakeCheckPermissionCallback(priv);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeSICSDriveCallback(sicsObject);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdb MakeSICSMemPar(char *name, int priv, float *address)
|
|
{
|
|
pHdb result = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
|
|
result = MakeHipadabaNode(name, HIPFLOAT, 1);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
pHcb = MakeCheckPermissionCallback(priv);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeMemGenSetCallback(address);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeMemGenReadCallback(address);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
pHdb MakeSICSROPar(char *name, hdbValue v)
|
|
{
|
|
pHdb result = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
|
|
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
copyHdbValue(&v, &result->value);
|
|
|
|
pHcb = MakeReadOnlyCallback();
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
|
|
hdbValue v)
|
|
{
|
|
pHdb result = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
|
|
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
copyHdbValue(&v, &result->value);
|
|
|
|
pHcb = MakeSICSWriteScriptCallback(setScript);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
|
|
pHcb = MakeSICSReadScriptCallback(readScript);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(result, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result, pHcb);
|
|
/**
|
|
* put into the list of nodes to check with the update task
|
|
*/
|
|
/* LLDnodeAppend(scriptUpdate,&result); */
|
|
SetHdbProperty(result, "sicscommand", setScript);
|
|
return result;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static void removeNodeFromUpdateList(pHdb node)
|
|
{
|
|
pHdb current = NULL;
|
|
int status;
|
|
char *objName = NULL;
|
|
|
|
objName = GetHipadabaPath(node);
|
|
if (objName != NULL) {
|
|
removePollObject(poller, objName);
|
|
free(objName);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void SICSDeleteNodeData(pHdb node)
|
|
{
|
|
pHdb tmp = NULL;
|
|
|
|
if (node == NULL) {
|
|
return;
|
|
}
|
|
|
|
removeNodeFromUpdateList(node);
|
|
DeleteCallbackChain(node);
|
|
while (node->child != NULL) {
|
|
tmp = node->child;
|
|
node->child = node->child->next;
|
|
SICSDeleteNodeData(tmp);
|
|
}
|
|
if (node->properties != NULL) {
|
|
DeleteStringDict(node->properties);
|
|
}
|
|
|
|
if (node->name != NULL) {
|
|
free(node->name);
|
|
}
|
|
ReleaseHdbValue(&node->value);
|
|
node->magic = 000000;
|
|
|
|
free(node);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void RemoveSICSPar(pHdb node, void *callData)
|
|
{
|
|
pHdb current = NULL, tmp = NULL;
|
|
|
|
if (node == NULL) {
|
|
return;
|
|
}
|
|
|
|
RemoveHdbNodeFromParent(node, NULL);
|
|
|
|
SICSDeleteNodeData(node);
|
|
}
|
|
|
|
/*===================== add functions =======================================*/
|
|
pHdb AddSICSHdbPar(pHdb parent, char *name, int priv, hdbValue v)
|
|
{
|
|
pHdb child = NULL;
|
|
|
|
child = MakeSICSHdbPar(name, priv, v);
|
|
if (child != NULL) {
|
|
AddHipadabaChild(parent, child, NULL);
|
|
}
|
|
return child;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdb AddSICSHdbROPar(pHdb parent, char *name, hdbValue v)
|
|
{
|
|
pHdb child = NULL;
|
|
|
|
child = MakeSICSROPar(name, v);
|
|
if (child != NULL) {
|
|
AddHipadabaChild(parent, child, NULL);
|
|
}
|
|
return child;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
pHdb AddSICSHdbMemPar(pHdb parent, char *name, int priv,
|
|
void *data, int datalength, int type, int length)
|
|
{
|
|
pHdb child = NULL;
|
|
pHdbCallback pHcb = NULL;
|
|
|
|
if (type == HIPINTVARAR || type == HIPFLOATVARAR) {
|
|
assert(0);
|
|
return NULL;
|
|
}
|
|
|
|
child = MakeHipadabaNode(name, type, length);
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
pHcb = MakeCheckPermissionCallback(priv);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(child, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(child, pHcb);
|
|
|
|
pHcb = MakeMemGenSetCallback(data);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(child, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(child, pHcb);
|
|
|
|
pHcb = MakeMemGenReadCallback(data);
|
|
if (pHcb == NULL) {
|
|
DeleteHipadabaNode(child, NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(child, pHcb);
|
|
AddHipadabaChild(parent, child, NULL);
|
|
|
|
return child;
|
|
}
|
|
|
|
/*==================== access support functions ==============================
|
|
This has become an eierlegendewollmilchsau function. I do not know how and when
|
|
that happened
|
|
==============================================================================*/
|
|
pHdb FindHdbParent(char *rootpath, char *relpath, char **namePtr,
|
|
SConnection * pCon)
|
|
{
|
|
/* for namePtr == NULL, implements also "find node" */
|
|
char *element;
|
|
char buffer[MAX_HDB_PATH];
|
|
pHdb node = NULL;
|
|
pHdb parent = NULL;
|
|
char *name;
|
|
char *slash;
|
|
pObjectDescriptor pDes;
|
|
int iret;
|
|
|
|
if (relpath[0] == '/' || rootpath == NULL) { /* absolute path */
|
|
iret = snprintf(buffer, sizeof buffer, "%s", relpath);
|
|
} else {
|
|
iret = snprintf(buffer, sizeof buffer, "%s/%s", rootpath, relpath);
|
|
}
|
|
if (iret < 0 || iret >= (int) sizeof(buffer)) {
|
|
SCWrite(pCon, "ERROR: path too long", eError);
|
|
return NULL;
|
|
}
|
|
element = buffer;
|
|
if (strncmp(element, "/sics/", 6) == 0) {
|
|
/* sics object case */
|
|
slash = strchr(element + 6, '/');
|
|
if (slash != NULL)
|
|
*slash = '\0'; /* split off object name */
|
|
|
|
pDes = FindCommandDescriptor(pServ->pSics, element + 6);
|
|
if (pDes == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: object %s not found", element);
|
|
return NULL;
|
|
}
|
|
node = pDes->parNode;
|
|
if (node == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: object %s does not use hipadaba",
|
|
element);
|
|
return NULL;
|
|
}
|
|
if (slash == NULL)
|
|
goto nodeFound;
|
|
*slash = '/';
|
|
element = slash + 1;
|
|
parent = node;
|
|
/* parent is sics object, path is relative to it */
|
|
} else {
|
|
/* normal path */
|
|
parent = GetHipadabaRoot();
|
|
}
|
|
while (1) {
|
|
slash = strchr(element, '/');
|
|
if (slash != NULL)
|
|
*slash = '\0'; /* split off next path element */
|
|
if (strcmp(element, "") == 0 || strcmp(element, ".") == 0) {
|
|
/* cases "//" and "/./" : do not move in tree */
|
|
if (slash == NULL) {
|
|
node = parent;
|
|
goto nodeFound;
|
|
}
|
|
*slash = '/';
|
|
element = slash + 1;
|
|
} else {
|
|
for (node = parent->child; node != NULL; node = node->next) {
|
|
if (strcasecmp(element, node->name) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (node == NULL) {
|
|
if (namePtr) { /* "find parent" case */
|
|
if (slash != NULL) { /* element is not the last in path */
|
|
*slash = '/';
|
|
SCPrintf(pCon, eError, "ERROR: parent of %s not found",
|
|
buffer);
|
|
return NULL;
|
|
}
|
|
/* the name must be taken from the end of relpath, as element is no longer valid */
|
|
*namePtr = relpath + (element - buffer);
|
|
return parent; /* parent found, and node does not yet exist */
|
|
}
|
|
/* "find node" case */
|
|
if (slash != NULL)
|
|
*slash = '/';
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", buffer);
|
|
return NULL;
|
|
}
|
|
/* node found */
|
|
if (slash == NULL)
|
|
goto nodeFound;
|
|
parent = node;
|
|
*slash = '/';
|
|
element = slash + 1;
|
|
}
|
|
}
|
|
nodeFound:
|
|
if (namePtr) { /* "find parent" case */
|
|
*namePtr = node->name;
|
|
SCPrintf(pCon, eError, "ERROR: node %s exists already", buffer);
|
|
return NULL;
|
|
}
|
|
return node; /* node found */
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
pHdb FindHdbNode(char *rootpath, char *relpath, SConnection * pCon)
|
|
{
|
|
return FindHdbParent(rootpath, relpath, NULL, pCon);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdb FindHdbIntern(char *path)
|
|
{
|
|
char *element, *slash;
|
|
pHdb parent = NULL;
|
|
pObjectDescriptor pDes = NULL;
|
|
|
|
element = path;
|
|
if(strncmp(element,"/sics/",6) == 0){
|
|
slash = strchr(element+6,'/');
|
|
if(slash != NULL){
|
|
*slash = '\0';
|
|
}
|
|
pDes = FindCommandDescriptor(pServ->pSics,element+6);
|
|
if(pDes == NULL){
|
|
return NULL;
|
|
}
|
|
parent = pDes->parNode;
|
|
if(parent == NULL){
|
|
return NULL;
|
|
}
|
|
if(slash == NULL){
|
|
return parent;
|
|
}
|
|
*slash = '/';
|
|
element = slash + 1;
|
|
} else {
|
|
parent = GetHipadabaRoot();
|
|
}
|
|
return GetHipadabaNode(parent,element);
|
|
}
|
|
/*--------------------------------------------------------------------------
|
|
* This does not use strlcpy, strlcat on purpose: it caused a bug
|
|
* There are so many length checks in the code anyway so that is
|
|
* not necessary either.
|
|
--------------------------------------------------------------------------*/
|
|
int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
|
|
{
|
|
pHdb node, parent;
|
|
int len, pos, l;
|
|
static char *sics = "/sics";
|
|
pObjectDescriptor pDes;
|
|
|
|
path[0] = '\0';
|
|
if (nodeArg == NULL) {
|
|
return 0;
|
|
}
|
|
/* determine path length and root node */
|
|
parent = nodeArg;
|
|
len = 0;
|
|
for (node = nodeArg; node != NULL && node != root; node = node->mama) {
|
|
len += strlen(node->name) + 1;
|
|
if (len >= (int) pathlen)
|
|
return 0; /* buffer overflow (recursive path?) */
|
|
parent = node;
|
|
}
|
|
|
|
/* check root and add prefix */
|
|
if (parent->mama != root) { /* not anchored in root */
|
|
pDes = FindCommandDescriptor(pServ->pSics, parent->name);
|
|
if (!pDes) {
|
|
return 0; /* not a sics object */
|
|
}
|
|
if (pDes->parNode != parent) {
|
|
/* node named as a sics object, but command is not related to node */
|
|
return 0;
|
|
}
|
|
l = strlen(sics);
|
|
len += l;
|
|
if (len > (int) pathlen)
|
|
return 0; /* buffer overflow */
|
|
strncpy(path, sics, l);
|
|
}
|
|
|
|
/* build the path backwards */
|
|
path[len] = '\0';
|
|
pos = len;
|
|
for (node = nodeArg; node != NULL && node != root; node = node->mama) {
|
|
len = strlen(node->name);
|
|
pos -= len;
|
|
assert(pos > 0);
|
|
strncpy(path + pos, node->name, len);
|
|
pos--;
|
|
path[pos] = '/';
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void RemoveSICSInternalCallbackFrom(pHdb node, void *internalID)
|
|
{
|
|
hdbPtrMessage m;
|
|
|
|
m.type = killPtr;
|
|
m.pPtr = internalID;
|
|
RecurseCallbackChains(node, (pHdbMessage) & m);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int RemoveParNodeCallback(char *name, pDummy object,
|
|
void *internalID)
|
|
{
|
|
if (object && object->pDescriptor->parNode) {
|
|
RemoveSICSInternalCallbackFrom(object->pDescriptor->parNode, internalID);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void RemoveSICSInternalCallback(void *internalID)
|
|
{
|
|
RemoveSICSInternalCallbackFrom(GetHipadabaRoot(), internalID);
|
|
ForEachCommand(RemoveParNodeCallback, internalID);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SICSHdbGetPar(void *obj, SConnection * pCon, char *path, hdbValue * v)
|
|
{
|
|
pHdb par = NULL;
|
|
int status;
|
|
char buffer[256];
|
|
pDummy pDum;
|
|
|
|
pDum = (pDummy) obj;
|
|
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
|
|
if (par == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
status = GetHipadabaPar(par, v, pCon);
|
|
if (status < 0) {
|
|
return status;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SICSHdbUpdatePar(void *obj, SConnection * pCon, char *path, hdbValue v)
|
|
{
|
|
pHdb par = NULL;
|
|
int status;
|
|
char buffer[256];
|
|
pDummy pDum;
|
|
|
|
pDum = (pDummy) obj;
|
|
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
|
|
if (par == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
status = UpdateHipadabaPar(par, v, pCon);
|
|
if (status < 0) {
|
|
return status;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SICSHdbSetPar(void *obj, SConnection * pCon, char *path, hdbValue v)
|
|
{
|
|
pHdb par = NULL;
|
|
int status;
|
|
char buffer[256];
|
|
pDummy pDum;
|
|
|
|
pDum = (pDummy) obj;
|
|
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
|
|
if (par == NULL) {
|
|
if (pCon != NULL) {
|
|
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
|
|
SCWrite(pCon, buffer, eError);
|
|
}
|
|
return SICSNOPAR;
|
|
}
|
|
|
|
status = SetHipadabaPar(par, v, pCon);
|
|
if (status <= 0) {
|
|
return status;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int InstallSICSNotify(pHdb node, SConnection * pCon, int id, int recurse)
|
|
{
|
|
pHdb currentChild = NULL;
|
|
pHdbCallback noty = NULL;
|
|
pHdbCallback treeChange = NULL;
|
|
|
|
treeChange = MakeTreeChangeCallback(pCon, id);
|
|
noty = MakeNotifyCallback(pCon, id);
|
|
if (noty == NULL || treeChange == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory installing callback", eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node, noty);
|
|
AppendHipadabaCallback(node, treeChange);
|
|
|
|
if (recurse == 1) {
|
|
currentChild = node->child;
|
|
while (currentChild != NULL) {
|
|
InstallSICSNotify(currentChild, pCon, id, recurse);
|
|
currentChild = currentChild->next;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void RemoveConnectionCallbacks(pHdb root, SConnection * pCon)
|
|
{
|
|
hdbPtrMessage dsm;
|
|
|
|
dsm.type = killPtr;
|
|
dsm.pPtr = pCon;
|
|
RecurseCallbackChains(root, (pHdbMessage) & dsm);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int ProcessSICSHdbPar(pHdb root, SConnection * pCon,
|
|
char *printPrefix, int argc, char *argv[])
|
|
{
|
|
hdbValue input;
|
|
pHdb parNode = NULL;
|
|
pDynString parData = NULL;
|
|
char error[512];
|
|
int i, status, firstValueArg;
|
|
float value;
|
|
|
|
assert(root != NULL && pCon != NULL);
|
|
|
|
if (argc < 1) {
|
|
SCWrite(pCon, "ERROR: no parameter to treat specified", eError);
|
|
return -1;
|
|
}
|
|
|
|
/* if the single argument is a number and the type of the root is a number
|
|
then we want to set the root itself to this number */
|
|
if (argc == 1
|
|
&& (root->value.dataType == HIPINT || root->value.dataType == HIPFLOAT)
|
|
&& sscanf(argv[0], "%f", &value) == 1) {
|
|
parNode = root;
|
|
firstValueArg = 0;
|
|
} else {
|
|
parNode = GetHipadabaNode(root, argv[0]);
|
|
firstValueArg = 1;
|
|
}
|
|
|
|
if (parNode == NULL) {
|
|
/* no error reporting here, upper level code might wish to continue
|
|
* processing commands after having tested for parameters.
|
|
*/
|
|
return -1;
|
|
}
|
|
|
|
if (argc > firstValueArg) {
|
|
/*
|
|
* setting the value is attempted.
|
|
*/
|
|
memset(&input, 0, sizeof(hdbValue));
|
|
input.dataType = parNode->value.dataType;
|
|
copyHdbValue(&parNode->value, &input);
|
|
parData = CreateDynString(64, 64);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory processing parameter", eError);
|
|
return 0;
|
|
}
|
|
for (i = firstValueArg; i < argc; i++) {
|
|
if (i > firstValueArg) {
|
|
DynStringConcat(parData, " ");
|
|
}
|
|
if (strchr(argv[i], ' ')) {
|
|
DynStringConcatChar(parData, '{');
|
|
DynStringConcat(parData, argv[i]);
|
|
DynStringConcatChar(parData, '}');
|
|
} else {
|
|
DynStringConcat(parData, argv[i]);
|
|
}
|
|
}
|
|
strcpy(error, "ERROR: ");
|
|
if (!readHdbValue(&input, GetCharArray(parData), error + 7, 512 - 7)) {
|
|
SCWrite(pCon, error, eError);
|
|
return 0;
|
|
}
|
|
DeleteDynString(parData);
|
|
status = SetHipadabaPar(parNode, input, pCon);
|
|
ReleaseHdbValue(&input);
|
|
if (status == 1) {
|
|
/* SCSendOK(pCon); do not send OK. this has to be done by the callback */
|
|
SCparChange(pCon);
|
|
}
|
|
return status;
|
|
} else {
|
|
/*
|
|
* reading is in demand
|
|
*/
|
|
status = GetHipadabaPar(parNode, &input, pCon);
|
|
if (status != 1) {
|
|
return 0;
|
|
}
|
|
parData = formatValue(input, parNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory reading parameter data", eError);
|
|
return 0;
|
|
}
|
|
DynStringInsert(parData, " = ", 0);
|
|
DynStringInsert(parData, argv[0], 0);
|
|
if (printPrefix != NULL) {
|
|
DynStringInsert(parData, printPrefix, 0);
|
|
}
|
|
SCWrite(pCon, GetCharArray(parData), eValue);
|
|
DeleteDynString(parData);
|
|
ReleaseHdbValue(&input);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void PrintSICSParList(pHdb node, SConnection * pCon, char *prefix)
|
|
{
|
|
char childPrefix[1024];
|
|
pHdb child = NULL;
|
|
pDynString value = NULL;
|
|
hdbValue v;
|
|
|
|
child = node->child;
|
|
while (child != NULL) {
|
|
if (child->value.dataType != HIPNONE) {
|
|
GetHipadabaPar(child, &v, pCon);
|
|
value = formatValue(child->value, child);
|
|
if (value != NULL) {
|
|
SCPrintf(pCon, eValue, "%s%s = %s", prefix, child->name,
|
|
GetCharArray(value));
|
|
DeleteDynString(value);
|
|
}
|
|
}
|
|
if (child->child != NULL) {
|
|
strlcpy(childPrefix, prefix, 1024);
|
|
strlcat(childPrefix, child->name, 1024);
|
|
strlcat(childPrefix, "/", 1024);
|
|
PrintSICSParList(child, pCon, prefix);
|
|
}
|
|
child = child->next;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void SaveSICSHipadaba(FILE * fd, pHdb node, char *prefix)
|
|
{
|
|
pHdb currentChild = NULL;
|
|
pDynString data = NULL;
|
|
hdbValue v;
|
|
|
|
currentChild = node->child;
|
|
while (currentChild != NULL) {
|
|
if (currentChild->value.dataType != HIPNONE
|
|
&& !isSICSHdbRO(currentChild)) {
|
|
data = formatValue(currentChild->value, currentChild);
|
|
if (data != NULL) {
|
|
fprintf(fd, "%s%s %s\n", prefix, currentChild->name,
|
|
GetCharArray(data));
|
|
DeleteDynString(data);
|
|
}
|
|
}
|
|
if (currentChild->child != NULL) {
|
|
/*
|
|
* build a new prefix string and recurse
|
|
*/
|
|
data = CreateDynString(64, 64);
|
|
if (data != NULL) {
|
|
DynStringCopy(data, prefix);
|
|
DynStringConcat(data, currentChild->name);
|
|
DynStringConcat(data, "/");
|
|
SaveSICSHipadaba(fd, currentChild, GetCharArray(data));
|
|
DeleteDynString(data);
|
|
}
|
|
}
|
|
currentChild = currentChild->next;
|
|
}
|
|
}
|
|
|
|
/*================ value helpers ============================================*/
|
|
pDynString formatValue(hdbValue v, pHdb node)
|
|
{
|
|
pDynString result = NULL;
|
|
int i;
|
|
char number[30];
|
|
char format[16];
|
|
|
|
result = CreateDynString(64, 64);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if(v.arrayLength > 65536){
|
|
DynStringCopy(result,"Data to big to format into text");
|
|
return result;
|
|
}
|
|
|
|
switch (v.dataType) {
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
snprintf(number, 30, "%d", v.v.intValue);
|
|
DynStringCopy(result, number);
|
|
break;
|
|
case HIPFLOAT:
|
|
if (node != NULL && GetHdbProperty(node, "fmt", format, sizeof format - 1)) {
|
|
snprintf(number, 30, format, v.v.doubleValue);
|
|
} else {
|
|
snprintf(number, 30, "%.6g", v.v.doubleValue);
|
|
}
|
|
DynStringCopy(result, number);
|
|
break;
|
|
case HIPTEXT:
|
|
DynStringCopy(result, v.v.text);
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
for (i = 0; i < v.arrayLength; i++) {
|
|
snprintf(number, 30, " %d", v.v.intArray[i]);
|
|
DynStringConcat(result, number);
|
|
}
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
if (node != NULL && GetHdbProperty(node, "fmt", format + 1, sizeof format - 2)) {
|
|
format[0] = ' ';
|
|
} else {
|
|
strcpy(format, " %.6g");
|
|
}
|
|
for (i = 0; i < v.arrayLength; i++) {
|
|
snprintf(number, 30, format, v.v.floatArray[i]);
|
|
DynStringConcat(result, number);
|
|
}
|
|
break;
|
|
case HIPFUNC:
|
|
DynStringConcat(result, "FUNCTION");
|
|
break;
|
|
case HIPOBJ:
|
|
DynStringConcat(result, "OBJECT");
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static char *getNextHdbNumber(char *pStart, char pNumber[80])
|
|
{
|
|
int charCount = 0;
|
|
pNumber[0] = '\0';
|
|
|
|
/* advance to first digit */
|
|
while (isspace(*pStart) && *pStart != '\0') {
|
|
pStart++;
|
|
}
|
|
if (*pStart == '\0') {
|
|
return NULL;
|
|
}
|
|
|
|
/* copy */
|
|
while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) {
|
|
pNumber[charCount] = *pStart;
|
|
pStart++;
|
|
charCount++;
|
|
}
|
|
pNumber[charCount] = '\0';
|
|
return pStart;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------*/
|
|
static int adjustDataLength(hdbValue * v, char *data)
|
|
{
|
|
char number[80];
|
|
int count = 0;
|
|
char *pPtr = NULL;
|
|
|
|
pPtr = data;
|
|
while ((pPtr = getNextHdbNumber(pPtr, number)) != NULL) {
|
|
count++;
|
|
}
|
|
if (count != v->arrayLength) {
|
|
v->arrayLength = count;
|
|
if (v->dataType == HIPINTVARAR) {
|
|
if (v->v.intArray != NULL) {
|
|
free(v->v.intArray);
|
|
}
|
|
v->v.intArray = malloc(count * sizeof(int));
|
|
if (v->v.intArray == NULL) {
|
|
return 0;
|
|
}
|
|
memset(v->v.intArray, 0, count * sizeof(int));
|
|
}
|
|
if (v->dataType == HIPFLOATVARAR) {
|
|
if (v->v.floatArray != NULL) {
|
|
free(v->v.floatArray);
|
|
}
|
|
v->v.floatArray = malloc(count * sizeof(double));
|
|
if (v->v.floatArray == NULL) {
|
|
return 0;
|
|
}
|
|
memset(v->v.floatArray, 0, count * sizeof(double));
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------------*/
|
|
int readHdbValue(hdbValue * v, char *data, char *error, int errlen)
|
|
{
|
|
int i, status;
|
|
int lValue;
|
|
double dValue;
|
|
char number[80];
|
|
char *pPtr = NULL;
|
|
void *objData;
|
|
|
|
switch (v->dataType) {
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
getNextHdbNumber(data, number);
|
|
status = sscanf(number, "%d", &v->v.intValue);
|
|
if (status != 1) {
|
|
snprintf(error, errlen, "Failed to convert [%.32s] to integer", data);
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPFLOAT:
|
|
getNextHdbNumber(data, number);
|
|
status = sscanf(number, "%lf", &v->v.doubleValue);
|
|
if (status != 1) {
|
|
snprintf(error, errlen, "Failed to convert [%.32s] to double", data);
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPTEXT:
|
|
if (v->v.text != NULL) {
|
|
free(v->v.text);
|
|
}
|
|
v->v.text = strdup(data);
|
|
v->arrayLength = strlen(data);
|
|
break;
|
|
case HIPINTVARAR:
|
|
if (!adjustDataLength(v, data)) {
|
|
snprintf(error, errlen,
|
|
"Out of memory allocating variable length data");
|
|
return 0;
|
|
}
|
|
case HIPINTAR:
|
|
for (i = 0; i < v->arrayLength; i++) {
|
|
data = getNextHdbNumber(data, number);
|
|
if (data == NULL) {
|
|
snprintf(error, errlen,
|
|
"Not enough values to parse, current index %d", i);
|
|
return 0;
|
|
}
|
|
status = sscanf(number, "%d", &lValue);
|
|
if (status != 1) {
|
|
snprintf(error, errlen, "Failed to convert [%.32s] to integer", data);
|
|
return 0;
|
|
}
|
|
v->v.intArray[i] = lValue;
|
|
}
|
|
break;
|
|
case HIPFLOATVARAR:
|
|
if (!adjustDataLength(v, data)) {
|
|
snprintf(error, errlen,
|
|
"Out of memory allocating variable length data");
|
|
return 0;
|
|
}
|
|
case HIPFLOATAR:
|
|
for (i = 0; i < v->arrayLength; i++) {
|
|
data = getNextHdbNumber(data, number);
|
|
if (data == NULL) {
|
|
snprintf(error, errlen,
|
|
"Not enough values to parse, current index %d", i);
|
|
return 0;
|
|
}
|
|
status = sscanf(number, "%lf", &dValue);
|
|
if (status != 1) {
|
|
snprintf(error, errlen, "Failed to convert [%.32s] to double", data);
|
|
return 0;
|
|
}
|
|
v->v.floatArray[i] = dValue;
|
|
}
|
|
break;
|
|
case HIPOBJ:
|
|
break;
|
|
case HIPFUNC:
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeSICSFunc(SICSOBJFunc func)
|
|
{
|
|
return MakeHdbFunc((voidFunc *) func);
|
|
}
|
|
|
|
/*================ interpreter interface ==================================*/
|
|
pHdb GetHipadabaRoot()
|
|
{
|
|
return root;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static char *hdbTypes[] = { "none",
|
|
"int",
|
|
"float",
|
|
"text",
|
|
"intar",
|
|
"floatar",
|
|
"intvarar",
|
|
"floatvarar",
|
|
"object",
|
|
"func",
|
|
NULL
|
|
};
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int convertHdbType(char *text)
|
|
{
|
|
int type;
|
|
|
|
type = 0;
|
|
while (hdbTypes[type] != NULL) {
|
|
if (strcasecmp(hdbTypes[type], text) == 0) {
|
|
break;
|
|
}
|
|
type++;
|
|
}
|
|
type--; /* we start counting at -1 */
|
|
return type;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static char *hdbTypeToText(int type)
|
|
{
|
|
return hdbTypes[type + 1];
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int MakeHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int type = 0, i, length = 0, priv = -1;
|
|
char *name = NULL;
|
|
pHdb parent = NULL;
|
|
pHdb child = NULL;
|
|
char buffer[512], buffer2[512];
|
|
hdbValue val;
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: not enough arguments to MakeHdbNode", eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* convert privilege
|
|
*/
|
|
priv = decodeSICSPriv(argv[2]);
|
|
/*
|
|
* convert datatype
|
|
*/
|
|
type = convertHdbType(argv[3]);
|
|
if (type > HIPFLOATVARAR) {
|
|
SCWrite(pCon,
|
|
"ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (type >= HIPINTAR) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: array length missing for array data type",
|
|
eError);
|
|
return 0;
|
|
} else {
|
|
length = atoi(argv[4]);
|
|
}
|
|
}
|
|
|
|
parent = FindHdbParent(NULL, argv[1], &name, pCon);
|
|
if (parent == NULL) {
|
|
return 0; /* error messages written inside FindHdbParent */
|
|
}
|
|
if (type != HIPNONE) {
|
|
val = makeHdbValue(type, length);
|
|
child = MakeSICSHdbPar(name, priv, val);
|
|
ReleaseHdbValue(&val);
|
|
} else {
|
|
child = MakeHipadabaNode(name, type, length);
|
|
}
|
|
if (child == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating node", eError);
|
|
return 0;
|
|
}
|
|
|
|
AddHipadabaChild(parent, child, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int MakeHdbScriptNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
int type = 0, i, length = 0;
|
|
char *name = NULL;
|
|
pHdb parent = NULL;
|
|
pHdb child = NULL;
|
|
pHdb current = NULL;
|
|
char *urgv[] = { "5", NULL };
|
|
char driver[] = { "hdb" };
|
|
char buffer[512], buffer2[512];
|
|
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: not enough arguments to MakeHdbNode", eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* convert datatype
|
|
*/
|
|
strtolower(argv[4]);
|
|
type = convertHdbType(argv[4]);
|
|
if (type >= 7) {
|
|
SCWrite(pCon,
|
|
"ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (type > 2) {
|
|
if (argc < 6) {
|
|
SCWrite(pCon, "ERROR: array length missing for array data type",
|
|
eError);
|
|
return 0;
|
|
} else {
|
|
length = atoi(argv[5]);
|
|
}
|
|
}
|
|
|
|
parent = FindHdbParent(NULL, argv[1], &name, pCon);
|
|
if (parent == NULL) {
|
|
return 0; /* error messages written inside FindHdbParent */
|
|
}
|
|
child = MakeSICSScriptPar(name, argv[3], argv[2],
|
|
makeHdbValue(type, length));
|
|
if (child == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating node", eError);
|
|
return 0;
|
|
}
|
|
|
|
AddHipadabaChild(parent, child, pCon);
|
|
/*
|
|
* have it polled automatically
|
|
*/
|
|
addPollObject(poller, pCon, GetHipadabaPath(child), driver, 1, urgv);
|
|
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
static int isNodeProtected(pHdb node)
|
|
{
|
|
pHdb current = NULL;
|
|
|
|
if (node->iprotected == 1) {
|
|
return 1;
|
|
}
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
if (isNodeProtected(current)) {
|
|
return 1;
|
|
}
|
|
current = current->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------------------*/
|
|
static int DeleteHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb killNode = NULL;
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to delete", eError);
|
|
return 0;
|
|
}
|
|
killNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (killNode == NULL) {
|
|
SCWrite(pCon, "ERROR: node to delete not found", eError);
|
|
return 0;
|
|
}
|
|
if (isNodeProtected(killNode)) {
|
|
SCWrite(pCon, "ERROR: this node or one of its children is protected",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
RemoveSICSPar(killNode, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL;
|
|
char error[512], value[132];
|
|
int i, status, priv;
|
|
pIDrivable pDriv = NULL;
|
|
pDummy data = NULL;
|
|
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: insufficient number of arguments to SetHdbNode",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
status = GetHdbProperty(targetNode,"priv",value,sizeof(value));
|
|
if(status == 1){
|
|
priv = decodeSICSPriv(value);
|
|
} else {
|
|
priv = usUser;
|
|
}
|
|
if (!SCMatchRights(pCon, priv)) {
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* special code to handle certain types of motors right
|
|
**/
|
|
status = GetHdbProperty(targetNode,"sicsdev",value,sizeof(value));
|
|
if(status == 1){
|
|
data = (pDummy)FindCommandData(pSics,value,NULL);
|
|
if(data != NULL){
|
|
pDriv = GetDrivableInterface(data);
|
|
if(pDriv != NULL){
|
|
status = StartDevice(pServ->pExecutor,value, data->pDescriptor,
|
|
data, pCon,RUNRUN, atof(argv[2]));
|
|
if(status == 1){
|
|
SCSendOK(pCon);
|
|
}
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (!cloneHdbValue(&targetNode->value, &newValue)) {
|
|
SCWrite(pCon, "ERROR: out of memory cloning node", eError);
|
|
return 0;
|
|
}
|
|
parData = CreateDynString(64, 64);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory reading parameter", eError);
|
|
return 0;
|
|
}
|
|
DynStringConcat(parData, argv[2]);
|
|
for (i = 3; i < argc; i++) {
|
|
DynStringConcat(parData, " ");
|
|
DynStringConcat(parData, argv[i]);
|
|
}
|
|
strcpy(error, "ERROR: ");
|
|
if (!readHdbValue(&newValue, GetCharArray(parData), error + 7, 512 - 7)) {
|
|
SCWrite(pCon, error, eError);
|
|
return 0;
|
|
}
|
|
DeleteDynString(parData);
|
|
status = SetHipadabaPar(targetNode, newValue, pCon);
|
|
ReleaseHdbValue(&newValue);
|
|
if (status == 1) {
|
|
/* SCSendOK(pCon); sending ok has to be done by the callback. */
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int UpdateHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL;
|
|
char error[512];
|
|
int i, status;
|
|
|
|
/*
|
|
if(!SCMatchRights(pCon,usUser)){
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to UpdateHdbNode",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
/* SCPrintf(pCon,eWarning, "Updating %s", argv[1]); */
|
|
if (argc > 2) {
|
|
if (!cloneHdbValue(&targetNode->value, &newValue)) {
|
|
SCWrite(pCon, "ERROR: out of memory cloning node", eError);
|
|
return 0;
|
|
}
|
|
parData = CreateDynString(64, 64);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory reading parameter", eError);
|
|
return 0;
|
|
}
|
|
DynStringConcat(parData, argv[2]);
|
|
for (i = 3; i < argc; i++) {
|
|
DynStringConcat(parData, " ");
|
|
DynStringConcat(parData, argv[i]);
|
|
}
|
|
strcpy(error, "ERROR: ");
|
|
if (!readHdbValue(&newValue, GetCharArray(parData),
|
|
error + 7, 512 - 7)) {
|
|
SCWrite(pCon, error, eError);
|
|
return 0;
|
|
}
|
|
DeleteDynString(parData);
|
|
} else {
|
|
memset(&newValue, 0, sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
}
|
|
status = UpdateHipadabaPar(targetNode, newValue, pCon);
|
|
ReleaseHdbValue(&newValue);
|
|
if (status == 1 && SCinMacro(pCon) == 0) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
static int ZipGetHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char error[512], oriPath[512];
|
|
int status = 0;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL, result= NULL;
|
|
Protocol protocol = normal_protocol;
|
|
OutCode outCode;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
memset(&newValue, 0, sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
if(newValue.dataType == HIPTEXT){
|
|
parData = formatValue(newValue, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
}
|
|
if ((protocol = isJSON(pCon, 0)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eValue;
|
|
|
|
result = CreateDynString(128, 128);
|
|
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
|
|
newValue.dataType);
|
|
SCWrite(pCon, GetCharArray(result), outCode);
|
|
DeleteDynString(parData);
|
|
DeleteDynString(result);
|
|
} else {
|
|
status = sendZippedNodeData(targetNode, newValue, pCon);
|
|
}
|
|
ReleaseHdbValue(&newValue);
|
|
return status;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
static int ZipReadHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char error[512], oriPath[512];
|
|
int status = 0;
|
|
pDynString parData = NULL, result= NULL;
|
|
Protocol protocol = normal_protocol;
|
|
OutCode outCode;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
if(targetNode->value.dataType == HIPTEXT){
|
|
parData = formatValue(targetNode->value, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
}
|
|
if ((protocol = isJSON(pCon,0)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eValue;
|
|
|
|
result = CreateDynString(128, 128);
|
|
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
|
|
targetNode->value.dataType);
|
|
SCWrite(pCon, GetCharArray(result), outCode);
|
|
DeleteDynString(parData);
|
|
DeleteDynString(result);
|
|
} else {
|
|
status = sendZippedNodeData(targetNode, targetNode->value, pCon);
|
|
}
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int BinReadHdbNode(SConnection *pCon, SicsInterp *pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
static int binMagic = 7333;
|
|
pHdb targetNode = NULL;
|
|
char oriPath[512];
|
|
hdbValue val;
|
|
int *data = NULL, i;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
val = targetNode->value;
|
|
switch(val.dataType){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
data = malloc(val.arrayLength+2*sizeof(int));
|
|
if(data == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in BinReadHdbNode",eError);
|
|
return 0;
|
|
}
|
|
data[0] = binMagic;
|
|
data[1] = val.arrayLength;
|
|
memcpy(data+2,val.v.intArray,val.arrayLength*sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
data = malloc(val.arrayLength+2*sizeof(int));
|
|
if(data == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in BinReadHdbNode",eError);
|
|
return 0;
|
|
}
|
|
data[0] = binMagic;
|
|
data[1] = val.arrayLength;
|
|
for(i = 0; i < val.arrayLength; i++){
|
|
data[i+2] = (int)(val.v.floatArray[i]*65536.);
|
|
}
|
|
break;
|
|
default:
|
|
SCWrite(pCon,"ERROR: cannot send binary data for this node type",eError);
|
|
return 0;
|
|
}
|
|
if(data != NULL){
|
|
ANETwrite(SCGetSockHandle(pCon),data,(val.arrayLength+2)*sizeof(int));
|
|
free(data);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL, result = NULL;
|
|
char error[512], oriPath[512];;
|
|
int i, status;
|
|
Protocol protocol = normal_protocol;
|
|
int outCode;
|
|
char value[80];
|
|
|
|
/*
|
|
if(strstr(argv[1],"values") != NULL){
|
|
printf("Found!!\n");
|
|
}
|
|
*/
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to print", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
/*
|
|
* if transfer = zip or bin, redirect to zip
|
|
*/
|
|
if (GetHdbProperty(targetNode, "transfer", value, 80) == 1) {
|
|
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
|
|
return ZipGetHdbNode(pCon, pSics, pData, argc, argv);
|
|
}
|
|
}
|
|
memset(&newValue, 0, sizeof(hdbValue));
|
|
/* ffr XXX I expect if status=0 then we don't have a valid value
|
|
Original code was causing a segfault for hdb text nodes
|
|
*/
|
|
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
|
|
return 0;
|
|
parData = formatValue(newValue, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
}
|
|
if ((protocol = isJSON(pCon, 0)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eValue;
|
|
|
|
result = CreateDynString(128, 128);
|
|
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
|
|
newValue.dataType);
|
|
SCWrite(pCon, GetCharArray(result), outCode);
|
|
DeleteDynString(parData);
|
|
DeleteDynString(result);
|
|
ReleaseHdbValue(&newValue);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int GetHdbVal(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL;
|
|
char error[512], oriPath[512];
|
|
int i, status, protocol, outCode;
|
|
char value[80];
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to print", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
memset(&newValue, 0, sizeof(hdbValue));
|
|
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
|
|
return 0;
|
|
parData = formatValue(newValue, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
} else {
|
|
if ((protocol = isJSON(pCon, 0)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eValue;
|
|
SCWrite(pCon, GetCharArray(parData), outCode);
|
|
DeleteDynString(parData);
|
|
ReleaseHdbValue(&newValue);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int GetHdbValIgnoreError(
|
|
SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
pDynString parData = NULL;
|
|
int protocol, outCode;
|
|
|
|
if (argc != 2) {
|
|
SCWrite(pCon, "ERROR: syntax must be: hvali <path>", eError);
|
|
return 0;
|
|
}
|
|
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
parData = formatValue(targetNode->value, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
}
|
|
if ((protocol = isJSON(pCon, 0)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eValue;
|
|
SCWrite(pCon, GetCharArray(parData), outCode);
|
|
DeleteDynString(parData);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int countChildren(pHdb node)
|
|
{
|
|
pHdb current = NULL;
|
|
int count = 0;
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
count++;
|
|
current = current->next;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int HdbNodeInfo(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char error[512], oriPath[512], info[512];
|
|
int i, status, length;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to get info", eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(oriPath, argv[1], 511);
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
length = targetNode->value.arrayLength;
|
|
if (length == 0) {
|
|
length = 1;
|
|
}
|
|
snprintf(info, 511, "%s,%d,%d",
|
|
hdbTypeToText(targetNode->value.dataType),
|
|
countChildren(targetNode), length);
|
|
SCWrite(pCon, info, eValue);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int HdbNodeVal(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
pDynString parData = NULL;
|
|
char error[512];
|
|
int i, status;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to print", eError);
|
|
return 0;
|
|
}
|
|
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
return 0;
|
|
}
|
|
memset(&newValue, 0, sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
parData = formatValue(newValue, targetNode);
|
|
if (parData == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
|
return 0;
|
|
}
|
|
SCWrite(pCon, GetCharArray(parData), eHdbValue);
|
|
DeleteDynString(parData);
|
|
ReleaseHdbValue(&newValue);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int isSICSHdbRO(pHdb node)
|
|
{
|
|
pHdbCallback current = NULL;
|
|
|
|
current = node->callBackChain;
|
|
while (current != NULL) {
|
|
if (current->userCallback == SICSReadOnlyCallback) {
|
|
return 1;
|
|
}
|
|
current = current->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static pDynString formatPlainList(pHdb node)
|
|
{
|
|
pHdb current;
|
|
pDynString result = NULL;
|
|
|
|
result = CreateDynString(128, 128);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
DynStringConcat(result, current->name);
|
|
DynStringConcat(result, "\n");
|
|
current = current->next;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static pDynString formatJSONList(pHdb node, int withValues)
|
|
{
|
|
pHdb current;
|
|
pDynString result = NULL;
|
|
pDynString data = NULL;
|
|
char *str;
|
|
|
|
if (node->child == NULL)
|
|
return NULL;
|
|
result = CreateDynString(128, 128);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (withValues)
|
|
DynStringCopy(result, "{");
|
|
else
|
|
DynStringCopy(result, "[");
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
DynStringConcatChar(result, '"');
|
|
DynStringConcat(result, current->name);
|
|
DynStringConcatChar(result, '"');
|
|
if (withValues) {
|
|
DynStringConcat(result, ": ");
|
|
if (current->value.dataType == HIPTEXT) {
|
|
DynStringConcatChar(result, '"');
|
|
data = formatValue(current->value, current);
|
|
if (data != NULL) {
|
|
/* lazy approach: remove \ and " */
|
|
for (str = GetCharArray(data); *str != 0; str++) {
|
|
if (*str == '\\' || *str == '"') {
|
|
*str = '_';
|
|
}
|
|
}
|
|
DynStringConcat(result, GetCharArray(data));
|
|
DeleteDynString(data);
|
|
}
|
|
DynStringConcatChar(result, '"');
|
|
} else {
|
|
if (current->value.dataType != HIPINT && current->value.dataType != HIPFLOAT) {
|
|
data = NULL;
|
|
} else {
|
|
data = formatValue(current->value, current);
|
|
}
|
|
if (data != NULL) {
|
|
DynStringConcat(result, GetCharArray(data));
|
|
DeleteDynString(data);
|
|
} else {
|
|
DynStringConcat(result, "null");
|
|
}
|
|
}
|
|
}
|
|
if (current->next != NULL)
|
|
DynStringConcat(result, ", ");
|
|
current = current->next;
|
|
}
|
|
|
|
if (withValues)
|
|
DynStringConcat(result, "}");
|
|
else
|
|
DynStringConcat(result, "]");
|
|
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static pDynString formatListWithVal(pHdb node)
|
|
{
|
|
pHdb current;
|
|
pDynString result = NULL;
|
|
pDynString data = NULL;
|
|
|
|
result = CreateDynString(128, 128);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
if (current->value.dataType != HIPNONE) {
|
|
DynStringConcat(result, current->name);
|
|
data = formatValue(current->value, current);
|
|
if (data != NULL) {
|
|
DynStringConcat(result, " = ");
|
|
DynStringConcat(result, GetCharArray(data));
|
|
DeleteDynString(data);
|
|
}
|
|
DynStringConcat(result, "\n");
|
|
}
|
|
current = current->next;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static pDynString formatClientList(pHdb node)
|
|
{
|
|
pHdb current;
|
|
pDynString result = NULL;
|
|
int length;
|
|
int i;
|
|
char number[50];
|
|
|
|
result = CreateDynString(128, 128);
|
|
if (result == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
DynStringConcat(result, current->name);
|
|
DynStringConcat(result, ",");
|
|
DynStringConcat(result, hdbTypeToText(current->value.dataType));
|
|
DynStringConcat(result, ",");
|
|
snprintf(number, 50, "%d", countChildren(current));
|
|
DynStringConcat(result, number);
|
|
DynStringConcat(result, ",");
|
|
if (current->value.dataType >= 3) {
|
|
length = current->value.arrayLength;
|
|
} else {
|
|
length = 1;
|
|
}
|
|
snprintf(number, 50, "%d", length);
|
|
DynStringConcat(result, number);
|
|
DynStringConcat(result, ",");
|
|
switch (current->value.dataType) {
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
snprintf(number, 50, "%d", current->value.v.intValue);
|
|
DynStringConcat(result, number);
|
|
break;
|
|
case HIPFLOAT:
|
|
snprintf(number, 50, "%lg", current->value.v.doubleValue);
|
|
DynStringConcat(result, number);
|
|
break;
|
|
case HIPTEXT:
|
|
DynStringConcat(result, current->value.v.text);
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
for (i = 0; i < length; i++) {
|
|
snprintf(number, 50, "%d", current->value.v.intArray[i]);
|
|
DynStringConcat(result, number);
|
|
if (i > length - 1) {
|
|
DynStringConcat(result, ",");
|
|
}
|
|
}
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
for (i = 0; i < length; i++) {
|
|
snprintf(number, 50, "%lf", current->value.v.floatArray[i]);
|
|
DynStringConcat(result, number);
|
|
if (i > length - 1) {
|
|
DynStringConcat(result, ",");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
DynStringConcat(result, "\n");
|
|
current = current->next;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
int pathArg = 1;
|
|
pDynString listData = NULL;
|
|
Protocol protocol = normal_protocol;
|
|
int outCode;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path to node to print", eError);
|
|
return 0;
|
|
}
|
|
|
|
if (argv[1][0] == '-') {
|
|
pathArg = 2;
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path to node to print", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
node = FindHdbNode(NULL, argv[pathArg], pCon);
|
|
if (node == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
/* do not modify arguments!
|
|
if (pathArg == 2) {
|
|
strtolower(argv[1]);
|
|
}
|
|
*/
|
|
outCode = eValue;
|
|
if (strcasecmp(argv[1], "-val") == 0) {
|
|
if (isJSON(pCon, 0)) {
|
|
listData = formatJSONList(node, 1);
|
|
outCode = eHdbEvent;
|
|
} else {
|
|
listData = formatListWithVal(node);
|
|
}
|
|
} else if (strcasecmp(argv[1], "-cli") == 0) {
|
|
listData = formatClientList(node);
|
|
} else {
|
|
if ((protocol = isJSON(pCon, 0)) == 1) {
|
|
listData = formatJSONList(node, 0);
|
|
outCode = eHdbEvent;
|
|
} else {
|
|
listData = formatPlainList(node);
|
|
}
|
|
}
|
|
if (listData == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to format list", eError);
|
|
return 0;
|
|
}
|
|
SCWrite(pCon, GetCharArray(listData), outCode);
|
|
DeleteDynString(listData);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int AutoNotifyHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
int id, status, recurse = 1;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and id in order to add notify",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
node = FindHdbNode(NULL, argv[1], pCon);
|
|
if (node == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
id = atoi(argv[2]);
|
|
|
|
if(argc > 3) {
|
|
recurse = atoi(argv[3]);
|
|
}
|
|
|
|
status = InstallSICSNotify(node, pCon, id, recurse);
|
|
if (status == 1) {
|
|
SCSendOK(pCon);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
int id;
|
|
hdbIDMessage m;
|
|
pObjectDescriptor pObj = NULL;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need callback id to remove", eError);
|
|
return 0;
|
|
}
|
|
id = atoi(argv[1]);
|
|
m.type = killID;
|
|
m.ID = id;
|
|
if(argc < 3){
|
|
RecurseCallbackChains(root, (pHdbMessage) & m);
|
|
} else {
|
|
pObj = FindCommandDescriptor(pSics,argv[2]);
|
|
if(pObj != NULL && pObj->parNode != NULL){
|
|
RecurseCallbackChains(pObj->parNode,(pHdbMessage)&m);
|
|
}
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static int LinkHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
char buffer[256];
|
|
pObjectDescriptor pDes = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and object name to link", eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
node = GetHipadabaNode(root, argv[1]);
|
|
if (node == NULL) {
|
|
snprintf(buffer, 255, "ERROR: path %s NOT found!", argv[1]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
pDes = FindCommandDescriptor(pSics, argv[2]);
|
|
if (pDes == NULL) {
|
|
snprintf(buffer, 255, "ERROR: failed to find object %s", argv[2]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
if (pDes->parNode == NULL) {
|
|
snprintf(buffer, 255,
|
|
"ERROR: Object %s does not use Hipadaba natively and thus cannot be linked",
|
|
argv[2]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
if (pDes->parNode->mama != NULL) {
|
|
snprintf(buffer, 255,
|
|
"ERROR: Object %s is already linked somewhere else", argv[2]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
AddHipadabaChild(node, pDes->parNode, pCon);
|
|
|
|
if (argc > 3) {
|
|
if (pDes->parNode->name != NULL) {
|
|
free(pDes->parNode->name);
|
|
}
|
|
pDes->parNode->name = strdup(argv[3]);
|
|
}
|
|
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int isArrayNode(pHdb node)
|
|
{
|
|
switch(node->value.dataType) {
|
|
case HIPINTAR:
|
|
case HIPFLOATAR:
|
|
case HIPINTVARAR:
|
|
case HIPFLOATVARAR:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ArrayCopyNode(pHdb to, SConnection *pCon, int argc, char *argv[])
|
|
{
|
|
pHdb from = NULL;
|
|
int iStart, iLength;
|
|
hdbValue fromData;
|
|
|
|
from = FindHdbNode(NULL,argv[3],pCon);
|
|
if(from == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: source node %s not found", argv[3]);
|
|
return 0;
|
|
}
|
|
if(!isArrayNode(from)){
|
|
SCPrintf(pCon,eError,"ERROR: %s is no array data node", argv[3]);
|
|
return 0;
|
|
}
|
|
|
|
iStart = 0;
|
|
iLength = from->value.arrayLength;
|
|
|
|
if(argc > 4) {
|
|
iStart = atoi(argv[4]);
|
|
if(iStart < 0) {
|
|
iStart = 0;
|
|
}
|
|
}
|
|
if(argc > 5) {
|
|
iLength = atoi(argv[5]);
|
|
if(iStart + iLength > from->value.arrayLength){
|
|
iLength = from->value.arrayLength - iStart - 1;
|
|
}
|
|
}
|
|
|
|
switch(from->value.dataType){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
fromData = MakeHdbIntArray(iLength, from->value.v.intArray+iStart);
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
fromData = MakeHdbFloatArray(iLength, from->value.v.floatArray+iStart);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
/* cannot really happen */
|
|
}
|
|
|
|
if(!copyHdbValue(&fromData, &to->value)) {
|
|
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
|
argv[3],argv[1]);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ArrayCopyOldHM(pHdb to, SConnection *pCon, int argc, char *argv[])
|
|
{
|
|
pHistMem hm = NULL;
|
|
int iStart, iLength;
|
|
int *data = NULL;
|
|
hdbValue copyData;
|
|
|
|
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
|
|
if(hm == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
|
|
return 0;
|
|
}
|
|
iStart = 0;
|
|
iLength = GetHistLength(hm);
|
|
|
|
if(argc > 4){
|
|
iStart = atoi(argv[4]);
|
|
iLength -= iStart;
|
|
}
|
|
|
|
if(argc > 5){
|
|
iLength = atoi(argv[5]);
|
|
}
|
|
|
|
if(iStart < 0){
|
|
iStart = 0;
|
|
}
|
|
|
|
if(iStart + iLength > GetHistLength(hm)){
|
|
iLength = GetHistLength(hm) - iStart - 1;
|
|
}
|
|
|
|
data = GetHistogramPointer(hm,pCon);
|
|
if(data == NULL){
|
|
SCPrintf(pCon,eError, "ERROR: failed to retrive HM data for %s", argv[3]);
|
|
return 0;
|
|
}
|
|
|
|
copyData = MakeHdbIntArray(iLength, data + iStart);
|
|
if(!copyHdbValue(©Data, &to->value)) {
|
|
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
|
argv[3],argv[1]);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ArrayCopyOldTB(pHdb to, SConnection *pCon, int argc, char *argv[])
|
|
{
|
|
pHistMem hm = NULL;
|
|
int iStart, iLength, timeLength, i;
|
|
const float *data = NULL;
|
|
double *ddata = NULL;
|
|
hdbValue copyData;
|
|
|
|
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
|
|
if(hm == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
|
|
return 0;
|
|
}
|
|
iStart = 0;
|
|
data = GetHistTimeBin(hm,&timeLength);
|
|
if(data == NULL){
|
|
SCPrintf(pCon,eError, "ERROR: failed to retrive time binning for HM %s", argv[3]);
|
|
return 0;
|
|
}
|
|
iLength = timeLength;
|
|
|
|
if(argc > 4){
|
|
iStart = atoi(argv[4]);
|
|
iLength -= iStart;
|
|
}
|
|
|
|
if(argc > 5){
|
|
iLength = atoi(argv[5]);
|
|
}
|
|
|
|
if(iStart < 0){
|
|
iStart = 0;
|
|
}
|
|
|
|
if(iStart + iLength > timeLength){
|
|
iLength = timeLength - iStart - 1;
|
|
}
|
|
|
|
ddata = malloc(iLength*sizeof(double));
|
|
if(ddata == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: out of memory copying %s time binning to %s",
|
|
argv[3],argv[1]);
|
|
return 0;
|
|
}
|
|
for(i = 0; i < iLength; i++){
|
|
ddata[i] = data[iStart+i];
|
|
}
|
|
copyData = MakeHdbFloatArray(iLength, ddata);
|
|
if(!copyHdbValue(©Data, &to->value)) {
|
|
SCPrintf(pCon,eError,
|
|
"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
|
argv[3],argv[1]);
|
|
return 0;
|
|
}
|
|
free(ddata);
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HdbArrayNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
pObjectDescriptor pDes = NULL;
|
|
int length, idx, ival, i;
|
|
int xstart, xend, xlength, ystart, yend, ylength;
|
|
double dval;
|
|
hdbValue v;
|
|
long sum;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: need at least three arguments to harray", eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
node = FindHdbNode(NULL, argv[1], pCon);
|
|
if (node == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: path %s NOT found!", argv[1]);
|
|
return 0;
|
|
}
|
|
if(!isArrayNode(node)){
|
|
SCPrintf(pCon,eError,"ERROR: %s is no array node!", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
if(strcmp(argv[2], "resize") == 0){
|
|
length = atoi(argv[3]);
|
|
v = makeHdbValue(node->value.dataType, length);
|
|
UpdateHipadabaPar(node, v, pCon);
|
|
ReleaseHdbValue(&v);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
if(strcmp(argv[2], "init") == 0){
|
|
v = makeHdbValue(node->value.dataType, node->value.arrayLength);
|
|
switch(node->value.dataType){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
ival = atoi(argv[3]);
|
|
for(i = 0; i < v.arrayLength; i++){
|
|
v.v.intArray[i] = ival;
|
|
}
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
dval = atof(argv[3]);
|
|
for(i = 0; i < v.arrayLength; i++){
|
|
v.v.intArray[i] = dval;
|
|
}
|
|
break;
|
|
}
|
|
UpdateHipadabaPar(node, v, pCon);
|
|
ReleaseHdbValue(&v);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
if(strcmp(argv[2],"sum") == 0){
|
|
if(argc < 9){
|
|
SCWrite(pCon,"ERROR: not enough arguments to harray sum", eError);
|
|
return 0;
|
|
}
|
|
xstart = atoi(argv[3]);
|
|
xend = atoi(argv[4]);
|
|
xlength = atoi(argv[5]);
|
|
ystart = atoi(argv[6]);
|
|
yend = atoi(argv[7]);
|
|
ylength = atoi(argv[8]);
|
|
sum = sumWindow(node->value.v.intArray,xstart,xend,xlength,ystart,yend,ylength);
|
|
SCPrintf(pCon,eValue,"sum = %ld", sum);
|
|
return 1;
|
|
}
|
|
|
|
if(strcmp(argv[2],"copynode") == 0){
|
|
return ArrayCopyNode(node, pCon, argc, argv);
|
|
}
|
|
if(strcmp(argv[2],"copyoldhm") == 0){
|
|
return ArrayCopyOldHM(node, pCon, argc, argv);
|
|
}
|
|
if(strcmp(argv[2],"copyoldtb") == 0){
|
|
return ArrayCopyOldTB(node, pCon, argc, argv);
|
|
}
|
|
|
|
idx = atoi(argv[2]);
|
|
if(idx < 0 || idx >= node->value.arrayLength ){
|
|
SCPrintf(pCon,eError,"ERROR: %d is out of range 0 - %d",
|
|
idx, node->value.arrayLength);
|
|
return 0;
|
|
}
|
|
switch(node->value.dataType){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
node->value.v.intArray[idx] = atoi(argv[3]);
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
node->value.v.floatArray[idx] = atof(argv[3]);
|
|
break;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn ChainCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdb slave = (pHdb) userData;
|
|
hdbValue vv, old;
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
if (slave != NULL) {
|
|
memset(&vv, 0, sizeof(hdbValue));
|
|
/*
|
|
The GetHipadabaPar here has to happen. Otherwise
|
|
necessary calculations to update the slave are not
|
|
performed.
|
|
*/
|
|
GetHipadabaPar(slave, &vv, mm->callData);
|
|
UpdateHipadabaPar(slave, vv, mm->callData);
|
|
ReleaseHdbValue(&vv);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ChainHdbNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb master = NULL, slave = NULL;
|
|
char buffer[512];
|
|
pHdbCallback kalle = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: insufficent number of arguments to hchain",
|
|
eError);
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
slave = GetHipadabaNode(root, argv[1]);
|
|
if (slave == NULL) {
|
|
snprintf(buffer, 511, "ERROR: slave %s not found", argv[1]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
master = GetHipadabaNode(root, argv[2]);
|
|
if (master == NULL) {
|
|
snprintf(buffer, 511, "ERROR: master %s not found", argv[1]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
|
|
kalle = MakeHipadabaCallback(ChainCallback, slave, NULL);
|
|
if (kalle == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating callback", eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(master, kalle);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
* This is actually SCInvoke but without advancing the context. I think this
|
|
* is only of local use. It makes sure that commands executed as Hipadaba
|
|
* commands get logged properly.
|
|
*/
|
|
static int HDBInvoke(SConnection * self, SicsInterp * pInter,
|
|
char *pCommand)
|
|
{
|
|
int iRet;
|
|
long lLen;
|
|
const char *pResult = NULL;
|
|
char *pBuffer = NULL, *pFile = NULL;
|
|
char pBueffel[80];
|
|
int i, iSpace;
|
|
|
|
assert(pInter);
|
|
|
|
/* print command to log files */
|
|
/*
|
|
for( i = 0; i < self->iFiles; i++)
|
|
{
|
|
if(self->pFiles[i])
|
|
{
|
|
fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
|
|
}
|
|
}
|
|
*/
|
|
|
|
/* print to command log if user or manager */
|
|
if (SCGetRights(self) <= usUser) {
|
|
if (self->pSock != NULL) {
|
|
sprintf(pBueffel, "sock %d>>", self->pSock->sockid);
|
|
}
|
|
}
|
|
|
|
/* invoke */
|
|
self->inUse++;
|
|
self->eInterrupt = eContinue;
|
|
/*
|
|
get first word of command
|
|
*/
|
|
iRet = InterpExecute(pInter, self, pCommand);
|
|
|
|
StatusFileTask(NULL); /* save changed parameters */
|
|
|
|
self->inUse--;
|
|
return iRet;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pDynString cmd = NULL, par = NULL;
|
|
pHdb current = NULL;
|
|
int status;
|
|
pHdbDataMessage mm = NULL;
|
|
hdbValue v;
|
|
|
|
/**
|
|
* TODO: this is a duplicate: resolve. It is still here because the old
|
|
* Hipadaba configuration commands still work
|
|
*/
|
|
if ((mm = GetHdbSetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
pCon = (SConnection *) mm->callData;
|
|
v = *(mm->v);
|
|
|
|
if (pCon == NULL) {
|
|
printf("Cannot invoke command without connection\n");
|
|
return hdbAbort;
|
|
}
|
|
|
|
if (v.dataType == HIPTEXT) {
|
|
if (strstr(v.v.text, "start") != NULL) {
|
|
cmd = CreateDynString(64, 64);
|
|
if (cmd == 0) {
|
|
SCWrite(pCon, "ERROR: out of memory in CommandSetCallback",
|
|
eError);
|
|
return 0;
|
|
}
|
|
DynStringCopy(cmd, node->value.v.text);
|
|
DynStringConcat(cmd, " ");
|
|
current = node->child;
|
|
while (current != NULL) {
|
|
par = formatValue(current->value, current);
|
|
if (par != NULL) {
|
|
DynStringConcat(cmd, GetCharArray(par));
|
|
DynStringConcat(cmd, " ");
|
|
DeleteDynString(par);
|
|
}
|
|
current = current->next;
|
|
}
|
|
// SendHdbStatusMessage(node,"start");
|
|
status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd));
|
|
// SendHdbStatusMessage(node,"stop");
|
|
DeleteDynString(cmd);
|
|
if (status == 1) {
|
|
return hdbContinue;
|
|
} else {
|
|
return hdbAbort;
|
|
}
|
|
} else {
|
|
SCWrite(pCon, "ERROR: this node only understands start as value",
|
|
eError);
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdbDataMessage mm = NULL;
|
|
|
|
if ((mm = GetHdbGetMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
|
|
hdbValue v2 = MakeHdbText("Nothing to get");
|
|
copyHdbValue(&v2, mm->v); /* MakeHdbText makes no strdup ! */
|
|
return hdbContinue;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SicsCommandNode(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
char *name = NULL;
|
|
pHdbCallback kalle = NULL;
|
|
pHdb parent = NULL, node = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: insufficent number of arguments to hcommand",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
parent = FindHdbParent(NULL, argv[1], &name, pCon);
|
|
if (parent == NULL) {
|
|
return 0; /* error message already written */
|
|
}
|
|
node = MakeHipadabaNode(name, HIPTEXT, 1);
|
|
if (node == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
|
|
return 0;
|
|
}
|
|
node->value.v.text = strdup(argv[2]);
|
|
node->value.arrayLength = strlen(argv[2]);
|
|
SetHdbProperty(node, "sicscommand", argv[2]);
|
|
// Set privillege of the node
|
|
if (argc > 3) {
|
|
SetHdbProperty(node, "priv", argv[3]);
|
|
}
|
|
|
|
kalle = MakeHipadabaCallback(CommandSetCallback, NULL, NULL);
|
|
if (kalle == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node, kalle);
|
|
|
|
kalle = MakeHipadabaCallback(CommandGetCallback, NULL, NULL);
|
|
if (kalle == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node, kalle);
|
|
|
|
AddHipadabaChild(parent, node, pCon);
|
|
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*======================= Property Functions ================================*/
|
|
static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char *val;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: need path key value as parameters", eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
if (argc == 4) {
|
|
SetHdbProperty(targetNode, argv[2], argv[3]);
|
|
} else {
|
|
val = Arg2Tcl(argc - 3, &argv[3], NULL, 0);
|
|
if (val) {
|
|
SetHdbProperty(targetNode, argv[2], val);
|
|
free(val);
|
|
}
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------*/
|
|
static int DelSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
SetHdbProperty(targetNode, argv[2], NULL);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int HasSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path key as parameters", eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCWrite(pCon, "ERROR: node not found", eError);
|
|
return 0;
|
|
}
|
|
if (HasHdbProperty(targetNode, argv[2])) {
|
|
SCPrintf(pCon, eValue, "%s", "true");
|
|
return 1;
|
|
} else {
|
|
SCPrintf(pCon, eValue, "%s", "false");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int GetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char buffer[512];
|
|
int status;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
status = GetHdbProperty(targetNode, argv[2], buffer, 511);
|
|
if (status != 1) {
|
|
SCPrintf(pCon, eError, "ERROR: %s has no property %s", argv[1], argv[2]);
|
|
return 0;
|
|
}
|
|
SCPrintf(pCon, eValue, "%s.%s = %s", argv[1], argv[2], buffer);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int GetSICSHdbPropertyVal(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char buffer[512];
|
|
int status;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
status = GetHdbProperty(targetNode, argv[2], buffer, 511);
|
|
if (status != 1) {
|
|
SCPrintf(pCon, eError, "ERROR: %s has no property %s", argv[1], argv[2]);
|
|
return 0;
|
|
}
|
|
SCPrintf(pCon, eValue, "%s", buffer);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char buffer[512];
|
|
const char *pKey = NULL;
|
|
pDynString data = NULL;
|
|
int genTclList = 0;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need path as parameter", eError);
|
|
return 0;
|
|
} else if (argc == 3) {
|
|
if (strncasecmp(argv[2], "tcl", 3) == 0)
|
|
genTclList = 1;
|
|
if (strncasecmp(argv[2], "tclesc", 6) == 0)
|
|
genTclList |= 2;
|
|
if (strncasecmp(argv[2], "tclnam", 6) == 0)
|
|
genTclList |= 4;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
|
return 0;
|
|
}
|
|
data = CreateDynString(64, 64);
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in ListSICSHdbProperty", eError);
|
|
return 0;
|
|
}
|
|
InitHdbPropertySearch(targetNode);
|
|
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
|
|
DynStringConcat(data, (char *) pKey);
|
|
if (genTclList) {
|
|
char *bp;
|
|
DynStringConcatChar(data, ' ');
|
|
if (genTclList & 4)
|
|
continue;
|
|
DynStringConcatChar(data, '{');
|
|
for (bp = buffer; *bp; ++bp) {
|
|
if (genTclList & 2 && (*bp == '{' || *bp == '}'))
|
|
DynStringConcatChar(data, '\\');
|
|
DynStringConcatChar(data, *bp);
|
|
}
|
|
DynStringConcatChar(data, '}');
|
|
DynStringConcatChar(data, ' ');
|
|
} else {
|
|
DynStringConcat(data, "=");
|
|
DynStringConcat(data, buffer);
|
|
DynStringConcat(data, "\n");
|
|
}
|
|
}
|
|
SCWrite(pCon, GetCharArray(data), eValue);
|
|
DeleteDynString(data);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int CallNotify(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
|
|
if(argc < 2) {
|
|
SCPrintf(pCon,eError, "ERROR: require path argument to %s", argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
node = GetHipadabaNode(GetHipadabaRoot(), argv[1]);
|
|
if(node == NULL){
|
|
SCPrintf(pCon,eError,"ERROR: cannot find node %s to notify", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
NotifyHipadabaPar(node,pCon);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int ANSTO_ListSICSHdbProperty(SConnection * pCon,
|
|
SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHdb targetNode = NULL;
|
|
char buffer[512], *globPtr = NULL;
|
|
int cmpSize = 0;
|
|
const char *pKey = NULL;
|
|
pDynString data = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need path and search string as parameters",
|
|
eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
|
if (targetNode == NULL) {
|
|
SCWrite(pCon, "ERROR: node not found", eError);
|
|
return 0;
|
|
}
|
|
data = CreateDynString(64, 64);
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in ListSICSHdbProperty", eError);
|
|
return 0;
|
|
}
|
|
InitHdbPropertySearch(targetNode);
|
|
|
|
/* Allow simple glob matches with '*' as a suffix
|
|
Eg hfindprop /hpath @*
|
|
*/
|
|
if ((globPtr = index(argv[2], '*')) != NULL) {
|
|
*globPtr = '\0';
|
|
}
|
|
cmpSize = strlen(argv[2]);
|
|
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
|
|
if (strncasecmp(argv[2], pKey, cmpSize) == 0) {
|
|
DynStringConcat(data, (char *) pKey);
|
|
DynStringConcat(data, " ");
|
|
DynStringConcat(data, buffer);
|
|
DynStringConcat(data, "\n");
|
|
}
|
|
}
|
|
SCWrite(pCon, GetCharArray(data), eValue);
|
|
DeleteDynString(data);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer,
|
|
pDynString result, int invertmatch)
|
|
{
|
|
char value[1024], *path = NULL;
|
|
pHdb current = NULL, search;
|
|
|
|
memset(value, 0, 1024);
|
|
if (strcmp(buffer, "*") == 0) {
|
|
if (GetHdbProperty(root, propname, value, 1023) == 1) {
|
|
if (!invertmatch) {
|
|
path = GetHipadabaPath(root);
|
|
DynStringConcat(result, path);
|
|
DynStringConcat(result, "\n");
|
|
free(path);
|
|
}
|
|
} else if (invertmatch) {
|
|
path = GetHipadabaPath(root);
|
|
DynStringConcat(result, path);
|
|
DynStringConcat(result, "\n");
|
|
free(path);
|
|
}
|
|
} else if (GetHdbProperty(root, propname, value, 1023) == 1) {
|
|
if (strstr(buffer, value) != NULL) {
|
|
if (!invertmatch) {
|
|
path = GetHipadabaPath(root);
|
|
DynStringConcat(result, path);
|
|
DynStringConcat(result, "\n");
|
|
free(path);
|
|
}
|
|
} else if (invertmatch) {
|
|
path = GetHipadabaPath(root);
|
|
DynStringConcat(result, path);
|
|
DynStringConcat(result, "\n");
|
|
free(path);
|
|
}
|
|
}
|
|
current = root->child;
|
|
while (current != NULL) {
|
|
search =
|
|
matchHdbProp(current, propname, buffer, result, invertmatch);
|
|
current = current->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb root = NULL;
|
|
pHdb foundNode = NULL;
|
|
char buffer[1024], *path = NULL;
|
|
int node = 1, prop = 2, propval = 3, invertmatch = 0;
|
|
pDynString matchList = NULL;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon,
|
|
"ERROR: need root, property name and target string for search",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (argc >= 5) {
|
|
if (strcasecmp(argv[1], "invert") == 0) {
|
|
invertmatch = 1;
|
|
node++;
|
|
prop++;
|
|
propval++;
|
|
}
|
|
}
|
|
memset(buffer, 0, 1024);
|
|
Arg2Text(argc - propval, &argv[propval], buffer, 1023);
|
|
root = GetHipadabaNode(GetHipadabaRoot(), argv[node]);
|
|
if (root == NULL) {
|
|
SCWrite(pCon, "ERROR: start node for search not found", eError);
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[prop]);
|
|
strtolower(buffer);
|
|
matchList = CreateDynString(128, 128);
|
|
foundNode =
|
|
matchHdbProp(root, argv[prop], buffer, matchList, invertmatch);
|
|
SCWrite(pCon, GetCharArray(matchList), eValue);
|
|
DeleteDynString(matchList);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int AddCheck(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
|
|
if(argc < 3) {
|
|
SCPrintf(pCon,eLogError, "ERROR: need at least node and key argument for %s",
|
|
argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
node = FindHdbNode(NULL, argv[1],pCon);
|
|
if (node == NULL) {
|
|
SCPrintf(pCon,eLogError, "ERROR: node %s to add check to not found", argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[2]);
|
|
if(strcmp(argv[2],"values") == 0) {
|
|
PrependHipadabaCallback(node,MakeHipadabaCallback(SICSValueCheckCallback,
|
|
NULL,NULL));
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
SCPrintf(pCon,eLogError,"ERROR: key %s for %s not recognized",
|
|
argv[2], argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SICSNotifyScriptCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
char *pPath = NULL;
|
|
int macro, status;
|
|
pHdbDataMessage mm = NULL;
|
|
SConnection *tstCon;
|
|
char script[256];
|
|
|
|
/*
|
|
* Deal with update messages
|
|
*/
|
|
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
|
return hdbContinue;
|
|
}
|
|
status = GetHdbProperty(node, "updatescript", script, sizeof(script));
|
|
if(status == 0){
|
|
tracePar(node->name,"ERROR: did not find updatescript property");
|
|
return hdbContinue;
|
|
}
|
|
|
|
if(mm->v != &node->value){
|
|
copyHdbValue(mm->v, &node->value);
|
|
}
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
|
|
if (status != TCL_OK) {
|
|
tracePar(node->name,"ERROR: %s while evaluating updatescript %s",
|
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)), script);
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int AddScriptNotify(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pHdb node = NULL;
|
|
|
|
if(argc < 3) {
|
|
SCWrite(pCon,"ERROR: Parameter missing, Usage: hscriptnotify node script",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
node = FindHdbNode(NULL,argv[1],pCon);
|
|
if (node == NULL) {
|
|
SCPrintf(pCon,eLogError, "ERROR: node %s to add script update not found",
|
|
argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
SetHdbProperty(node,"updatescript",strdup(argv[2]));
|
|
AppendHipadabaCallback(node,MakeHipadabaCallback(SICSNotifyScriptCallback,
|
|
NULL,NULL));
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
/*======================= Factory Functions =================================*/
|
|
void killSICSHipadaba()
|
|
{
|
|
if (root != NULL) {
|
|
DeleteHipadabaNode(root, NULL);
|
|
}
|
|
root = NULL;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
extern int HdbNodeFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); /* from sicshdbfactory.c */
|
|
/*---------------------------------------------------------------------------*/
|
|
int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
|
|
root = MakeHipadabaNode("/", HIPNONE, 0);
|
|
AddCommand(pSics, "hmake", MakeHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hfactory", HdbNodeFactory, NULL, NULL);
|
|
AddCommand(pSics, "hmakescript", MakeHdbScriptNode, NULL, NULL);
|
|
AddCommand(pSics, "hattach", SICSHdbAdapter, NULL, NULL);
|
|
AddCommand(pSics, "hsubsamplehm", HdbSubSample, NULL, NULL);
|
|
AddCommand(pSics, "hdel", DeleteHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hset", SetHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hupdate", UpdateHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hget", GetHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hval", GetHdbVal, NULL, NULL);
|
|
AddCommand(pSics, "hvali", GetHdbValIgnoreError, NULL, NULL);
|
|
AddCommand(pSics, "hzipget", ZipGetHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hzipread", ZipReadHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hbinread", BinReadHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL);
|
|
AddCommand(pSics, "hlink", LinkHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL);
|
|
AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL);
|
|
AddCommand(pSics, "hcommand", SicsCommandNode, NULL, NULL);
|
|
AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL);
|
|
AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hdelprop", DelSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hgetprop", GetSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL);
|
|
AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hpropexists", HasSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hfindprop", ANSTO_ListSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL);
|
|
AddCommand(pSics, "haddcheck",AddCheck, NULL, NULL);
|
|
AddCommand(pSics, "hscriptnotify",AddScriptNotify, NULL, NULL);
|
|
|
|
InstallSICSPoll(pCon, pSics, pData, argc, argv);
|
|
poller = (pSicsPoll) FindCommandData(pSics, "sicspoll", "SicsPoll");
|
|
|
|
return 1;
|
|
}
|