2491 lines
75 KiB
C
2491 lines
75 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
|
|
*
|
|
* TODO: separate this into two modules: sicshipadaba proper and sicshipadabaint for the
|
|
* interpreter interface.
|
|
*/
|
|
#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"
|
|
|
|
/*== there can be only hipadaba in SICS, some globals to care for that == */
|
|
static pHdb root = NULL;
|
|
static pSicsPoll poller = NULL;
|
|
/*=============== common callback functions used for SICS ===========================*/
|
|
static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
int *testPriv = NULL;
|
|
SConnection *pCon = NULL;
|
|
|
|
pCon = (SConnection *)callData;
|
|
testPriv = (int *)userData;
|
|
|
|
/*
|
|
* 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 1;
|
|
}
|
|
|
|
assert(testPriv != NULL);
|
|
|
|
if(SCMatchRights(pCon,*testPriv) == 1){
|
|
return 1;
|
|
} else {
|
|
return SICSCBPERM;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeCheckPermissionCallback(int priv){
|
|
int *testPriv = NULL;
|
|
|
|
testPriv = malloc(sizeof(int));
|
|
if(testPriv == NULL){
|
|
return NULL;
|
|
}
|
|
*testPriv = priv;
|
|
return MakeHipadabaCallback(SICSCheckPermissionCallback, testPriv,free,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static int SICSSetUpdateCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
return UpdateHipadabaPar(node,v,callData);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSetUpdateCallback(){
|
|
return MakeHipadabaCallback(SICSSetUpdateCallback, NULL,NULL,-1,-1);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
SConnection *pCon = NULL;
|
|
|
|
pCon = (SConnection *)callData;
|
|
|
|
if(pCon != NULL){
|
|
SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError);
|
|
}
|
|
return SICSCBRO;
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeReadOnlyCallback(){
|
|
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static int SICSDriveCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
SConnection *pCon = NULL;
|
|
pDummy dum = NULL;
|
|
|
|
pCon = (SConnection *)callData;
|
|
dum = (pDummy)userData;
|
|
assert(pCon != NULL && dum != NULL);
|
|
return StartDevice(pServ->pExecutor,node->name,dum->pDescriptor,
|
|
userData, pCon, (float)v.v.doubleValue);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSDriveCallback(void *sicsObject){
|
|
return MakeHipadabaCallback(SICSDriveCallback, sicsObject,NULL,-1,-1);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
static SConnection *defCon = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDummy dum = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
float value;
|
|
|
|
pCon = (SConnection *)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;
|
|
v.v.doubleValue = (double)value;
|
|
} else {
|
|
if(defCon != NULL){
|
|
value = pDriv->GetValue(dum,defCon);
|
|
node->value.v.doubleValue = (double)value;
|
|
v.v.doubleValue = (double)value;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){
|
|
return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject,NULL,-1,-1);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
SConnection *pCon;
|
|
commandContext context;
|
|
}HdbCBInfo;
|
|
|
|
static int isJSON(SConnection *pCon) {
|
|
char proName[128];
|
|
void *pData;
|
|
|
|
if(SCinMacro(pCon)){
|
|
return 0;
|
|
}
|
|
pData = FindCommandData(pServ->pSics, "protocol","Protocol");
|
|
ProtocolGet(pCon, pData, proName, 128);
|
|
if (strcmp(proName, "json") == 0)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int formatNameValue(int jsonSet, char *name, char *value, pDynString result) {
|
|
if (name == NULL) {
|
|
if (jsonSet) {
|
|
} else {
|
|
}
|
|
} else if (value == NULL) {
|
|
if (jsonSet) {
|
|
DynStringInsert(result,"\": ", 0);
|
|
DynStringInsert(result,name,0);
|
|
DynStringInsert(result,"{\"", 0);
|
|
DynStringConcat(result,"}");
|
|
} else {
|
|
DynStringInsert(result," =",0);
|
|
DynStringInsert(result,name,0);
|
|
}
|
|
} else {
|
|
if (jsonSet) {
|
|
DynStringCopy(result,"{\"");
|
|
DynStringConcat(result,name);
|
|
DynStringConcat(result,"\": ");
|
|
DynStringConcat(result,value);
|
|
DynStringConcat(result,"}");
|
|
} else {
|
|
DynStringCopy(result,name);
|
|
DynStringConcat(result," = ");
|
|
DynStringConcat(result,value);
|
|
}
|
|
}
|
|
return jsonSet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static int SICSNotifyCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
HdbCBInfo *cbInfo = NULL;
|
|
pDynString printedData = NULL;
|
|
pDynString result = NULL;
|
|
char *pPath = NULL;
|
|
int protocol = 0, outCode;
|
|
|
|
cbInfo = (HdbCBInfo *)userData;
|
|
pPath = GetHipadabaPath(node);
|
|
result = CreateDynString(128,128);
|
|
if ((protocol = isJSON(cbInfo->pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
|
|
if(v.arrayLength < 100){
|
|
printedData = formatValue(v);
|
|
if(pPath == NULL || printedData == NULL || result == NULL){
|
|
SCWriteInContext(cbInfo->pCon,"ERROR: out of memory formatting data" ,
|
|
eEvent,cbInfo->context);
|
|
/*
|
|
* no need to interrupt something because writing data to a client does
|
|
* not work
|
|
*/
|
|
return 1;
|
|
}
|
|
formatNameValue(protocol, pPath, GetCharArray(printedData), result);
|
|
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
|
outCode,cbInfo->context);
|
|
DeleteDynString(printedData);
|
|
} else {
|
|
formatNameValue(protocol,"!!datachange!!", pPath, result);
|
|
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
|
outCode,cbInfo->context);
|
|
}
|
|
free(pPath);
|
|
DeleteDynString(result);
|
|
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){
|
|
HdbCBInfo *cbInfo = NULL;
|
|
|
|
cbInfo = malloc(sizeof(HdbCBInfo));
|
|
if(cbInfo == NULL){
|
|
return NULL;
|
|
}
|
|
cbInfo->pCon = pCon;
|
|
cbInfo->context = SCGetContext(pCon);
|
|
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free,id,pCon->ident);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int TreeChangeCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char *path = NULL;
|
|
char buffer[1024];
|
|
pDynString result = NULL;
|
|
int protocol = 0, outCode;
|
|
|
|
result = CreateDynString(128,128);
|
|
HdbCBInfo *cbInfo = (HdbCBInfo *)userData;
|
|
|
|
if(cbInfo != NULL && cbInfo->pCon != NULL){
|
|
path = GetHipadabaPath(node);
|
|
if ((protocol = isJSON(cbInfo->pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
formatNameValue(protocol, "treechange", path, result);
|
|
SCWriteInContext(cbInfo->pCon,GetCharArray(result),outCode,cbInfo->context);
|
|
DeleteDynString(result);
|
|
free(path);
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){
|
|
HdbCBInfo *cbInfo = NULL;
|
|
|
|
cbInfo = malloc(sizeof(HdbCBInfo));
|
|
if(cbInfo == NULL){
|
|
return NULL;
|
|
}
|
|
cbInfo->pCon = pCon;
|
|
cbInfo->context = SCGetContext(pCon);
|
|
return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free,id,pCon->ident);
|
|
}
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static int SICSScriptWriteCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char *command = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDynString newVal = NULL;
|
|
char error[1024];
|
|
int status;
|
|
|
|
command = (char *)userData;
|
|
pCon = (SConnection *)callData;
|
|
|
|
assert(command != NULL && pCon != NULL);
|
|
|
|
newVal = formatValue(v);
|
|
if(newVal == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory setting parameter",eError);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
static pHdbCallback MakeSICSWriteScriptCallback(char *script){
|
|
return MakeHipadabaCallback(SICSScriptWriteCallback, strdup(script),free,-1,-1);
|
|
}
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static int SICSScriptReadCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char *command = NULL, *data = NULL, *equal = NULL;
|
|
SConnection *pCon = NULL;
|
|
pDynString newVal = NULL;
|
|
char error[1024];
|
|
int status;
|
|
|
|
command = (char *)userData;
|
|
pCon = (SConnection *)callData;
|
|
|
|
assert(command != NULL && pCon != NULL);
|
|
|
|
/*
|
|
* evaluate
|
|
*/
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics),command);
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* decode result. This handles both the case of the standard SICS answer
|
|
* something = anything
|
|
* as well as a plain value alone
|
|
*/
|
|
data = Tcl_GetStringResult(InterpGetTcl(pServ->pSics));
|
|
if(data == NULL){
|
|
SCWrite(pCon,"ERROR: no result returned from script",eError);
|
|
return 0;
|
|
}
|
|
equal = strchr(data,'=');
|
|
if(equal != NULL){
|
|
data = equal + 1;
|
|
}
|
|
strcpy(error,"ERROR: ");
|
|
status = readHdbValue(&node->value,data, error+7, 1024-7);
|
|
if(status != 1){
|
|
SCWrite(pCon,error,eError);
|
|
return 0;
|
|
}
|
|
return status;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static pHdbCallback MakeSICSReadScriptCallback(char *script){
|
|
return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),
|
|
free,-1,-1);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
int min;
|
|
int max;
|
|
}hdbIntRange, *pHdbIntRange;
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SICSIntRangeCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char buffer[256];
|
|
pHdbIntRange range = NULL;
|
|
SConnection *pCon = NULL;
|
|
int status = 1;
|
|
|
|
range = (pHdbIntRange)userData;
|
|
pCon = (SConnection *)callData;
|
|
|
|
assert(range != NULL);
|
|
|
|
if(v.v.intValue > range->max || v.v.intValue < range->min) {
|
|
status = SICSCBRANGE;
|
|
if(pCon != NULL){
|
|
snprintf(buffer,255,"ERROR: %d is not within permitted range: %d to %d",
|
|
(int)v.v.intValue, range->min, range->max);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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,-1,-1);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
double min;
|
|
double max;
|
|
}hdbFloatRange, *pHdbFloatRange;
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SICSFloatRangeCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char buffer[256];
|
|
pHdbFloatRange range = NULL;
|
|
SConnection *pCon = NULL;
|
|
int status = 1;
|
|
|
|
range = (pHdbFloatRange)userData;
|
|
pCon = (SConnection *)callData;
|
|
|
|
assert(range != NULL);
|
|
|
|
if(v.v.doubleValue > range->max || v.v.doubleValue < range->min) {
|
|
status = SICSCBRANGE;
|
|
if(pCon != NULL){
|
|
snprintf(buffer,255,"ERROR: %lf is not within permitted range: %lf to %lf",
|
|
v.v.doubleValue, range->min, range->max);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int MemReadCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
float *value = NULL;
|
|
|
|
value = (float *)userData;
|
|
if(value != NULL){
|
|
v.dataType = HIPFLOAT;
|
|
v.v.doubleValue = (float) *value;
|
|
node->value.v.doubleValue = (double)*value;
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int MemGenReadCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
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 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemGenReadCallback(void *address){
|
|
return MakeHipadabaCallback(MemReadCallback, address,
|
|
NULL,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemReadCallback(float *address){
|
|
return MakeHipadabaCallback(MemReadCallback, address,
|
|
NULL,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int MemSetCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
float *value = NULL;
|
|
|
|
value = (float *)userData;
|
|
if(value != NULL){
|
|
*value = (float)v.v.doubleValue;
|
|
}
|
|
UpdateHipadabaPar(node,v,callData);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int MemGenSetCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
const char *pPtr = NULL;
|
|
|
|
if(v.dataType != node->value.dataType){
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
switch(node->value.dataType){
|
|
case HIPINT:
|
|
memcpy(userData,&v.v.intValue,sizeof(int));
|
|
break;
|
|
case HIPFLOAT:
|
|
memcpy(userData,&v.v.doubleValue,sizeof(double));
|
|
break;
|
|
case HIPTEXT:
|
|
strncpy((char *)userData,(const char *)v.v.text,
|
|
node->value.arrayLength);
|
|
break;
|
|
case HIPINTAR:
|
|
memcpy(userData,&v.v.intArray,node->value.arrayLength*sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
memcpy(userData,&v.v.floatArray,
|
|
node->value.arrayLength*sizeof(double));
|
|
break;
|
|
default:
|
|
assert(0);
|
|
return 0;
|
|
break;
|
|
}
|
|
UpdateHipadabaPar(node,v,callData);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemSetCallback(float *address){
|
|
return MakeHipadabaCallback(MemSetCallback, address,
|
|
NULL,-1,-1);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemGenSetCallback(void *address){
|
|
return MakeHipadabaCallback(MemSetCallback, address,
|
|
NULL,-1,-1);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void killHdbValue(void *pData){
|
|
hdbValue *v = NULL;
|
|
|
|
v = (hdbValue *)pData;
|
|
if(v == NULL){
|
|
return;
|
|
}
|
|
ReleaseHdbValue(v);
|
|
free(v);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SICSIntFixedCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
hdbValue *allowed = NULL;
|
|
SConnection *pCon = NULL;
|
|
int i;
|
|
|
|
allowed = (hdbValue *)userData;
|
|
pCon = (SConnection *)callData;
|
|
assert(allowed != NULL && allowed->dataType == HIPINTAR);
|
|
for(i = 0; i < allowed->arrayLength; i++){
|
|
if(v.v.intValue == allowed->v.intArray[i]){
|
|
return 1;
|
|
}
|
|
}
|
|
if(pCon != NULL){
|
|
SCWrite(pCon,"ERROR: value is not in the list of allowed values",eError);
|
|
}
|
|
return SICSCBBADFIXED;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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,-1,-1);
|
|
}
|
|
/*============= Parameter Creation ===========================================*/
|
|
pHdb MakeSICSHdbPar(char *name, int priv, 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 = MakeCheckPermissionCallback(priv);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
|
|
|
pHcb = MakeSetUpdateCallback();
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
|
|
|
return result;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdb CreateSICSHdbPar(char *name, int priv, int dataType,
|
|
int length, void *data){
|
|
return MakeSICSHdbPar(name,priv,makeHdbData(dataType,
|
|
length,data));
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
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,HCBSET,pHcb);
|
|
|
|
pHcb = MakeSICSDriveCallback(sicsObject);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
|
|
|
pHcb = MakeSICSReadDriveCallback(sicsObject);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBREAD,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,HCBSET,pHcb);
|
|
|
|
pHcb = MakeMemSetCallback(address);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBSET,pHcb);
|
|
|
|
pHcb = MakeMemReadCallback(address);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBREAD,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,HCBSET,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,HCBSET,pHcb);
|
|
|
|
pHcb = MakeSICSReadScriptCallback(readScript);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBREAD,pHcb);
|
|
/**
|
|
* put into the list of nodes to check with the update task
|
|
*/
|
|
/* LLDnodeAppend(scriptUpdate,&result); */
|
|
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
|
|
int dataType, int length, void *data){
|
|
return MakeSICSScriptPar(name,setScript,readScript,
|
|
makeHdbData(dataType, length,data));
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
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);
|
|
while(node->child != NULL){
|
|
tmp = node->child;
|
|
node->child = node->child->next;
|
|
SICSDeleteNodeData(tmp);
|
|
}
|
|
if(node->properties != NULL){
|
|
DeleteStringDict(node->properties);
|
|
}
|
|
DeleteCallbackChain(node->writeCallbacks);
|
|
DeleteCallbackChain(node->updateCallbacks);
|
|
DeleteCallbackChain(node->readCallbacks);
|
|
|
|
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 =======================================*/
|
|
int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v){
|
|
pHdb child = NULL;
|
|
|
|
child = MakeSICSHdbPar(name,priv,v);
|
|
if(child == NULL){
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(node,child,NULL);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int AddSICSHdbROPar(pHdb node, char *name, hdbValue v){
|
|
pHdb child = NULL;
|
|
|
|
child = MakeSICSROPar(name,v);
|
|
if(child == NULL){
|
|
return 0;
|
|
}
|
|
AddHipadabaChild(node,child,NULL);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int AddSICSHdbMemPar(pHdb node, 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 0;
|
|
}
|
|
|
|
child = MakeHipadabaNode(name,type,length);
|
|
if(child == NULL){
|
|
return 0;
|
|
}
|
|
|
|
pHcb = MakeCheckPermissionCallback(priv);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(child,NULL);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(child,HCBSET,pHcb);
|
|
|
|
pHcb = MakeMemGenSetCallback(data);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(child,NULL);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(child,HCBSET,pHcb);
|
|
|
|
pHcb = MakeMemGenReadCallback(data);
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(child,NULL);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(child,HCBREAD,pHcb);
|
|
AddHipadabaChild(node,child,NULL);
|
|
|
|
return 1;
|
|
}
|
|
/*==================== access suport functions ==============================*/
|
|
int SICSHdbGetPar(void *obj, SConnection *pCon,
|
|
char *path, int dataType, void *data, int length){
|
|
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 = GetHdbPar(par,dataType,data,length,pCon);
|
|
if(status < 0){
|
|
return status;
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SICSHdbUpdatePar(void *obj, SConnection *pCon,
|
|
char *path, int dataType,void *data, int dataLength ){
|
|
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 = UpdateHdbPar(par,dataType,data,dataLength,pCon);
|
|
if(status < 0){
|
|
return status;
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SICSHdbSetPar(void *obj, SConnection *pCon,
|
|
char *path, int dataType,void *data, int dataLength ){
|
|
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 = SetHdbPar(par,dataType,data,dataLength,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, HCBUPDATE, noty);
|
|
AppendHipadabaCallback(node, HCBTREE, treeChange);
|
|
|
|
if(recurse == 1){
|
|
currentChild = node->child;
|
|
while(currentChild != NULL){
|
|
InstallSICSNotify(currentChild,pCon,id,recurse);
|
|
currentChild = currentChild->next;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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;
|
|
|
|
assert(root != NULL && pCon != NULL);
|
|
|
|
if(argc < 1){
|
|
SCWrite(pCon,"ERROR: no parameter to treat specified",eError);
|
|
return -1;
|
|
}
|
|
|
|
parNode = GetHipadabaNode(root,argv[0]);
|
|
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 > 1) {
|
|
/*
|
|
* 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 = 1; i < argc; i++){
|
|
DynStringConcat(parData," ");
|
|
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);
|
|
SCparChange(pCon);
|
|
}
|
|
return status;
|
|
} else {
|
|
/*
|
|
* reading is in demand
|
|
*/
|
|
status = GetHipadabaPar(parNode,&input, pCon);
|
|
if(status != 1){
|
|
return 0;
|
|
}
|
|
parData = formatValue(input);
|
|
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);
|
|
if(value != NULL){
|
|
SCPrintf(pCon,eValue,"%s%s = %s", prefix, child->name,
|
|
GetCharArray(value));
|
|
DeleteDynString(value);
|
|
}
|
|
}
|
|
if(child->child != NULL){
|
|
strncpy(childPrefix,prefix,1024);
|
|
strncat(childPrefix,child->name, 1024);
|
|
strncat(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)){
|
|
GetHipadabaPar(currentChild,&v,NULL);
|
|
data = formatValue(currentChild->value);
|
|
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){
|
|
pDynString result = NULL;
|
|
int i;
|
|
char number[30];
|
|
|
|
result = CreateDynString(64,64);
|
|
if(result == NULL){
|
|
return NULL;
|
|
}
|
|
switch(v.dataType){
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
snprintf(number,30,"%d", v.v.intValue);
|
|
DynStringCopy(result,number);
|
|
break;
|
|
case HIPFLOAT:
|
|
snprintf(number,30,"%12.4f", 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:
|
|
for(i = 0; i < v.arrayLength; i++){
|
|
snprintf(number,30," %12.4f", v.v.floatArray[i]);
|
|
DynStringConcat(result,number);
|
|
}
|
|
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;
|
|
|
|
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 %s 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 %s to double",
|
|
data);
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPTEXT:
|
|
if(v->v.text != NULL){
|
|
free(v->v.text);
|
|
}
|
|
v->v.text = strdup(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 %s 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 %s to double",
|
|
data);
|
|
return 0;
|
|
}
|
|
v->v.floatArray[i] = dValue;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
/*================ interpreter interface ==================================*/
|
|
pHdb GetHipadabaRoot(){
|
|
return root;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static char *hdbTypes[] = {"none",
|
|
"int",
|
|
"float",
|
|
"text",
|
|
"intar",
|
|
"floatar",
|
|
"intvarar",
|
|
"floatvarar",
|
|
NULL};
|
|
/*-------------------------------------------------------------------------*/
|
|
static int convertHdbType(char *text){
|
|
int type;
|
|
|
|
type = 0;
|
|
while(hdbTypes[type] != NULL){
|
|
if(strcmp(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 *pPtr = NULL;
|
|
pHdb parent = NULL;
|
|
pHdb child = NULL;
|
|
char buffer[512], buffer2[512];
|
|
|
|
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
|
|
*/
|
|
strtolower(argv[3]);
|
|
type = convertHdbType(argv[3]);
|
|
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 < 5){
|
|
SCWrite(pCon,"ERROR: array length missing for array data type",
|
|
eError);
|
|
return 0;
|
|
} else {
|
|
length = atoi(argv[3]);
|
|
}
|
|
}
|
|
|
|
/* split off last path element */
|
|
strncpy(buffer,argv[1],511);
|
|
pPtr = strrchr(buffer,'/');
|
|
if(pPtr == NULL){
|
|
SCWrite(pCon,"ERROR: invalid path specification",
|
|
eError);
|
|
return 0;
|
|
}
|
|
*pPtr = '\0';
|
|
pPtr++;
|
|
if(strlen(pPtr) < 1) {
|
|
parent = root;
|
|
} else {
|
|
parent = GetHipadabaNode(root,buffer);
|
|
}
|
|
if(parent == NULL){
|
|
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
|
|
buffer);
|
|
SCWrite(pCon,buffer2,eError);
|
|
return 0;
|
|
}
|
|
if(type != HIPNONE){
|
|
child = MakeSICSHdbPar(pPtr, priv, makeHdbValue(type,length));
|
|
} else {
|
|
child = MakeHipadabaNode(pPtr,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 *pPtr = 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]);
|
|
}
|
|
}
|
|
|
|
/* split off last path element */
|
|
strncpy(buffer,argv[1],511);
|
|
pPtr = strrchr(buffer,'/');
|
|
if(pPtr == NULL){
|
|
SCWrite(pCon,"ERROR: invalid path specification",
|
|
eError);
|
|
return 0;
|
|
}
|
|
*pPtr = '\0';
|
|
pPtr++;
|
|
if(strlen(pPtr) < 1) {
|
|
parent = root;
|
|
} else {
|
|
parent = GetHipadabaNode(root,buffer);
|
|
}
|
|
if(parent == NULL){
|
|
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
|
|
buffer);
|
|
SCWrite(pCon,buffer2,eError);
|
|
return 0;
|
|
}
|
|
child = MakeSICSScriptPar(pPtr, 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->protected == 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 = GetHipadabaNode(root,argv[1]);
|
|
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 pHdb locateSICSNode(SicsInterp *pSics, SConnection *pCon, char *path){
|
|
pHdb result = NULL;
|
|
char *pPtr = NULL, sicsObj[128], error[256];
|
|
pDummy pDum = NULL;
|
|
CommandList *pCom = NULL;
|
|
|
|
if(strstr(path,"/sics/") != NULL){
|
|
pPtr = stptok(path,sicsObj,128,"/");
|
|
pPtr = stptok(pPtr,sicsObj,128,"/");
|
|
pPtr = stptok(pPtr,sicsObj,128,"/");
|
|
strtolower(sicsObj);
|
|
pCom = FindCommand(pSics,sicsObj);
|
|
if(pCom == NULL) {
|
|
snprintf(error,255,"ERROR: object %s not found",sicsObj);
|
|
SCWrite(pCon,error,eError);
|
|
return NULL;
|
|
}
|
|
pDum = (pDummy)pCom->pData;
|
|
if(pDum == NULL){
|
|
snprintf(error,255,"ERROR: object %s has no data",sicsObj);
|
|
SCWrite(pCon,error,eError);
|
|
return NULL;
|
|
}
|
|
if(pDum->pDescriptor->parNode == NULL){
|
|
snprintf(error,255,"ERROR: object %s does not use Hipadaba",sicsObj);
|
|
SCWrite(pCon,error,eError);
|
|
return NULL;
|
|
}
|
|
result = GetHipadabaNode(pDum->pDescriptor->parNode,pPtr);
|
|
} else {
|
|
result = GetHipadabaNode(root,path);
|
|
}
|
|
if(result == NULL){
|
|
snprintf(error,255,"ERROR: node %s NOT found",path);
|
|
SCWrite(pCon,error,eError);
|
|
}
|
|
return result;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SetHdbNode(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 < 3) {
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to SetHdbNode",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
if(!cloneHdbValue(&targetNode->value,&newValue)){
|
|
SCWrite(pCon,"ERROR: out of mmeory cloning node",
|
|
eError);
|
|
return 0;
|
|
}
|
|
parData = CreateDynString(64,64);
|
|
if(parData == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory reading parameter",eError);
|
|
return 0;
|
|
}
|
|
for(i = 2; 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);
|
|
}
|
|
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 = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
if(argc > 2){
|
|
if(!cloneHdbValue(&targetNode->value,&newValue)){
|
|
SCWrite(pCon,"ERROR: out of mmeory cloning node",
|
|
eError);
|
|
return 0;
|
|
}
|
|
parData = CreateDynString(64,64);
|
|
if(parData == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory reading parameter",eError);
|
|
return 0;
|
|
}
|
|
for(i = 2; 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;
|
|
}
|
|
} else {
|
|
GetHipadabaPar(targetNode,&newValue,pCon);
|
|
}
|
|
status = UpdateHipadabaPar(targetNode,newValue,pCon);
|
|
ReleaseHdbValue(&newValue);
|
|
if(status == 1){
|
|
SCSendOK(pCon);
|
|
}
|
|
return status;
|
|
}
|
|
/*-----------------------------------------------------------------------------*/
|
|
static int GetHdbNode(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;
|
|
int protocol = 0, outCode;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path to node to print",eError);
|
|
return 0;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
memset(&newValue,0,sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
parData = formatValue(newValue);
|
|
if(parData == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory formatting data",eError);
|
|
return 0;
|
|
}
|
|
if ((protocol = isJSON(pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
|
|
formatNameValue(protocol, oriPath, NULL, parData);
|
|
SCWrite(pCon,GetCharArray(parData),outCode);
|
|
DeleteDynString(parData);
|
|
ReleaseHdbValue(&newValue);
|
|
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------------*/
|
|
static int ZipGetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pHdb targetNode = NULL;
|
|
hdbValue newValue;
|
|
char error[512], oriPath[512];
|
|
int i, status;
|
|
int *iData = NULL;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path to node",eError);
|
|
return 0;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
memset(&newValue,0,sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
switch(newValue.dataType){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
for(i = 0; i < newValue.arrayLength; i++){
|
|
newValue.v.intArray[i] = htonl(newValue.v.intArray[i]);
|
|
}
|
|
SCWriteZipped(pCon,oriPath, newValue.v.intArray,
|
|
newValue.arrayLength*sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
iData = (int *)malloc(newValue.arrayLength*sizeof(int));
|
|
if(iData == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in ZipGetHdbNode",eError);
|
|
return 0;
|
|
}
|
|
memset(iData,0,newValue.arrayLength*sizeof(int));
|
|
for(i = 0; i < newValue.arrayLength; i++){
|
|
iData[i] = htonl((int)newValue.v.floatArray[i]*65536.);
|
|
}
|
|
SCWriteZipped(pCon,oriPath, iData,
|
|
newValue.arrayLength*sizeof(int));
|
|
free(iData);
|
|
break;
|
|
default:
|
|
SCWrite(pCon,"ERROR: zipped writing not supported for this datatype",
|
|
eError);
|
|
return 0;
|
|
}
|
|
ReleaseHdbValue(&newValue);
|
|
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;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
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 = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
memset(&newValue,0,sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode, &newValue, pCon);
|
|
parData = formatValue(newValue);
|
|
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->writeCallbacks;
|
|
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){
|
|
pHdb current;
|
|
pDynString result = NULL;
|
|
pDynString data = NULL;
|
|
|
|
if (node->child == NULL) return NULL;
|
|
result = CreateDynString(128,128);
|
|
if(result == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
if(node->child->value.dataType == HIPNONE)
|
|
DynStringCopy(result,"[");
|
|
else
|
|
DynStringCopy(result,"{");
|
|
|
|
current = node->child;
|
|
while(current != NULL){
|
|
DynStringConcat(result,"\"");
|
|
DynStringConcat(result,current->name);
|
|
DynStringConcat(result,"\"");
|
|
if(current->value.dataType != HIPNONE){
|
|
data = formatValue(current->value);
|
|
if(data != NULL){
|
|
DynStringConcat(result,": ");
|
|
DynStringConcat(result,GetCharArray(data));
|
|
DeleteDynString(data);
|
|
}
|
|
}
|
|
if (current->next != NULL) DynStringConcat(result,", ");
|
|
current = current->next;
|
|
}
|
|
|
|
if(node->child->value.dataType == HIPNONE)
|
|
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);
|
|
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,"%lf",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;
|
|
int protocol = 0, outCode;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path to node to print",eError);
|
|
return 0;
|
|
}
|
|
|
|
if(strchr(argv[1],'-') != NULL){
|
|
pathArg = 2;
|
|
if(argc < 3){
|
|
SCWrite(pCon,"ERROR: need path to node to print",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
node = locateSICSNode(pSics,pCon,argv[pathArg]);
|
|
if(node == NULL){
|
|
return 0;
|
|
}
|
|
|
|
if(pathArg == 2) {
|
|
strtolower(argv[1]);
|
|
}
|
|
if(strcmp(argv[1],"-val") == 0){
|
|
listData = formatListWithVal(node);
|
|
} else if(strcmp(argv[1],"-cli") == 0){
|
|
listData = formatClientList(node);
|
|
} else {
|
|
if ((protocol = isJSON(pCon)) == 1) {
|
|
listData = formatJSONList(node);
|
|
outCode = eHdbEvent;
|
|
} else {
|
|
listData = formatPlainList(node);
|
|
outCode = eEvent;
|
|
}
|
|
}
|
|
if(listData == NULL){
|
|
SCWrite(pCon,"ERROR: failed to format list",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if( (strcmp(argv[1],"-val") == 0) || (strcmp(argv[1],"-cli") == 0) ){
|
|
SCWrite(pCon,GetCharArray(listData),eValue);
|
|
} else {
|
|
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;
|
|
|
|
if(argc < 3) {
|
|
SCWrite(pCon,"ERROR: need path and id in order to add notify",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
node = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(node == NULL){
|
|
return 0;
|
|
}
|
|
|
|
id = atoi(argv[2]);
|
|
|
|
status = InstallSICSNotify(node, pCon, id, 1);
|
|
if(status == 1){
|
|
SCSendOK(pCon);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int RemoveHdbCallback(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
int id;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need callback id to remove",
|
|
eError);
|
|
return 0;
|
|
}
|
|
id = atoi(argv[1]);
|
|
RemoveHipadabaCallback(root,id);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pHdb node = NULL;
|
|
char buffer[256];
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = 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;
|
|
}
|
|
|
|
pCom = FindCommand(pSics,argv[2]);
|
|
if(pCom == NULL){
|
|
snprintf(buffer,255,"ERROR: failed to find object %s", argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return 0;
|
|
}
|
|
pDum = pCom->pData;
|
|
if(pDum == NULL || pDum->pDescriptor->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(pDum->pDescriptor->parNode->mama != NULL){
|
|
snprintf(buffer,255,
|
|
"ERROR: Object %s is already linked somewhere else",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return 0;
|
|
}
|
|
|
|
AddHipadabaChild(node,pDum->pDescriptor->parNode,pCon);
|
|
|
|
if(argc > 3){
|
|
if(pDum->pDescriptor->parNode->name != NULL){
|
|
free(pDum->pDescriptor->parNode->name);
|
|
}
|
|
pDum->pDescriptor->parNode->name = strdup(argv[3]);
|
|
}
|
|
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ChainCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
pHdb slave = (pHdb)userData;
|
|
hdbValue vv, old;
|
|
|
|
if(slave != NULL){
|
|
old = slave->value;
|
|
memset(&vv,0,sizeof(hdbValue));
|
|
GetHipadabaPar(slave,&vv,callData);
|
|
if(!compareHdbValue(old,vv)){
|
|
UpdateHipadabaPar(slave, vv, callData);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
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, -1,-1);
|
|
if(kalle == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory creating callback",eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(master,HCBUPDATE, kalle);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int CommandSetCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
SConnection *pCon = (SConnection *)callData;
|
|
pDynString cmd = NULL, par = NULL;
|
|
pHdb current = NULL;
|
|
int status;
|
|
|
|
if(pCon == NULL){
|
|
printf("Cannot invoke command without connection\n");
|
|
return 0;
|
|
}
|
|
|
|
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);
|
|
if(par != NULL){
|
|
DynStringConcat(cmd, GetCharArray(par));
|
|
DynStringConcat(cmd," ");
|
|
DeleteDynString(par);
|
|
}
|
|
current = current->next;
|
|
}
|
|
status = SCInvoke(pCon, pServ->pSics,GetCharArray(cmd));
|
|
DeleteDynString(cmd);
|
|
return status;
|
|
} else {
|
|
SCWrite(pCon,"ERROR: this node only understands start as value",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int CommandGetCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
hdbValue v2 = MakeHdbText("Nothing to get");
|
|
v = v2;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SicsCommandNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
char buffer[512], buffer2[512], *pPtr = NULL;
|
|
pHdbCallback kalle = NULL;
|
|
pHdb parent = NULL, node = NULL;
|
|
|
|
if(argc < 3) {
|
|
SCWrite(pCon,"ERROR: insufficent number of arguments to hcommand",
|
|
eError);
|
|
}
|
|
if(!SCMatchRights(pCon,usMugger)){
|
|
return 0;
|
|
}
|
|
|
|
/* split off last path element */
|
|
strncpy(buffer,argv[1],511);
|
|
pPtr = strrchr(buffer,'/');
|
|
if(pPtr == NULL){
|
|
SCWrite(pCon,"ERROR: invalid path specification",
|
|
eError);
|
|
return 0;
|
|
}
|
|
*pPtr = '\0';
|
|
pPtr++;
|
|
if(strlen(pPtr) < 1) {
|
|
parent = root;
|
|
} else {
|
|
parent = GetHipadabaNode(root,buffer);
|
|
}
|
|
if(parent == NULL){
|
|
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
|
|
buffer);
|
|
SCWrite(pCon,buffer2,eError);
|
|
return 0;
|
|
}
|
|
node = MakeHipadabaNode(pPtr, 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]);
|
|
|
|
kalle = MakeHipadabaCallback(CommandSetCallback,NULL, NULL, -1,-1);
|
|
if(kalle == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in hcommand",eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node,HCBSET, kalle);
|
|
|
|
kalle = MakeHipadabaCallback(CommandGetCallback,NULL, NULL, -1,-1);
|
|
if(kalle == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in hcommand",eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node,HCBREAD, 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 buffer[512];
|
|
|
|
if(argc < 4) {
|
|
SCWrite(pCon,"ERROR: need path key value as parameters",eError);
|
|
return 0;
|
|
}
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
SCWrite(pCon,"ERROR: node not found",eError);
|
|
return 0;
|
|
}
|
|
Arg2Text(argc-3, &argv[3], buffer,512);
|
|
SetHdbProperty(targetNode,argv[2], buffer);
|
|
SCSendOK(pCon);
|
|
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 key as parameters",eError);
|
|
return 0;
|
|
}
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
if(targetNode == NULL){
|
|
SCWrite(pCon,"ERROR: node not found",eValue);
|
|
return 0;
|
|
}
|
|
status = GetHdbProperty(targetNode,argv[2],buffer,511);
|
|
if(status != 1){
|
|
SCWrite(pCon,"ERROR: attribute not found",eValue);
|
|
return 0;
|
|
}
|
|
SCPrintf(pCon,eValue,"%s.%s = %s", argv[1], argv[2], 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;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path as parameter",eError);
|
|
return 0;
|
|
}
|
|
targetNode = locateSICSNode(pSics,pCon,argv[1]);
|
|
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);
|
|
while((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL){
|
|
DynStringConcat(data,(char *)pKey);
|
|
DynStringConcat(data,"=");
|
|
DynStringConcat(data,buffer);
|
|
DynStringConcat(data,"\n");
|
|
}
|
|
SCWrite(pCon,GetCharArray(data), eValue);
|
|
DeleteDynString(data);
|
|
return 1;
|
|
}
|
|
/*======================= Factory Functions =================================*/
|
|
void killSICSHipadaba(){
|
|
if(root != NULL){
|
|
DeleteHipadabaNode(root,NULL);
|
|
}
|
|
root = NULL;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
|
|
root = MakeHipadabaNode("/",HIPNONE,0);
|
|
AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL);
|
|
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
|
|
AddCommand(pSics,"hattach", SICSHdbAdapter, 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,"hzipget",ZipGetHdbNode, 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,"hval", HdbNodeVal, NULL, NULL);
|
|
AddCommand(pSics,"hchain", ChainHdbNode, NULL, NULL);
|
|
AddCommand(pSics,"hcommand",SicsCommandNode, NULL, NULL);
|
|
AddCommand(pSics,"hsetprop",SetSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics,"hgetprop",GetSICSHdbProperty, NULL, NULL);
|
|
AddCommand(pSics,"hlistprop",ListSICSHdbProperty, NULL, NULL);
|
|
|
|
InstallSICSPoll(pCon,pSics,pData,argc,argv);
|
|
poller = (pSicsPoll)FindCommandData(pSics,"sicspoll","SicsPoll");
|
|
|
|
return 1;
|
|
}
|