2851 lines
86 KiB
C
2851 lines
86 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"
|
|
#include <splitter.h>
|
|
#include "sicsobj.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);
|
|
/*=============== 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,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static int SICSSetUpdateCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
return UpdateHipadabaPar(node,v,callData);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSetUpdateCallback(){
|
|
return MakeHipadabaCallback(SICSSetUpdateCallback, NULL,NULL,-1,NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
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,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------------------*/
|
|
static int SICSDriveCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
SConnection *pCon = NULL;
|
|
pDummy dum = NULL;
|
|
char pSicsdev[80];
|
|
|
|
pCon = (SConnection *)callData;
|
|
dum = (pDummy)userData;
|
|
assert(pCon != NULL && dum != NULL);
|
|
if(GetHdbProperty(node,"sicsdev",pSicsdev,79)){
|
|
return StartDevice(pServ->pExecutor,pSicsdev,dum->pDescriptor,
|
|
userData, pCon, (float)v.v.doubleValue);
|
|
} else {
|
|
return StartDevice(pServ->pExecutor,node->name,dum->pDescriptor,
|
|
userData, pCon, (float)v.v.doubleValue);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSDriveCallback(void *sicsObject){
|
|
return MakeHipadabaCallback(SICSDriveCallback, sicsObject,NULL,-1,NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
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;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SICSFuncCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
pHdb par[64], current = NULL;
|
|
int nPar = 0;
|
|
SICSOBJFunc func = NULL;
|
|
|
|
assert(node->value.dataType == HIPFUNC);
|
|
if(userData == NULL || callData == NULL){
|
|
printf("Great Badness in calling SICSFuncCallback\n");
|
|
return 0;
|
|
}
|
|
|
|
current = node->child;
|
|
while(current != NULL){
|
|
par[nPar] = current;
|
|
nPar++;
|
|
current = current->next;
|
|
}
|
|
func = (SICSOBJFunc)node->value.v.obj;
|
|
if(func != NULL){
|
|
return func((pSICSOBJ)userData,(SConnection *)callData, node, par,nPar);
|
|
} else {
|
|
printf("Great Badness in calling SICSFuncCallback\n");
|
|
return 0;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSFuncCallback(void *obj){
|
|
return MakeHipadabaCallback(SICSFuncCallback, obj,NULL,-1,NULL);
|
|
}
|
|
/*--------------------------------------------------------------------------------------*/
|
|
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){
|
|
return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject,NULL,-1,NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
SConnection *pCon;
|
|
commandContext context;
|
|
}HdbCBInfo;
|
|
|
|
static Protocol isJSON(SConnection *pCon) {
|
|
char proName[128];
|
|
void *pData;
|
|
|
|
if(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;
|
|
|
|
switch(protocol) {
|
|
case normal_protocol:
|
|
DynStringCopy(result,name);
|
|
DynStringConcat(result," = ");
|
|
DynStringConcat(result,value);
|
|
break;
|
|
case json_protocol:
|
|
switch(hdtype){
|
|
case HIPNONE:
|
|
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,"\": \"");
|
|
DynStringConcat(result,value);
|
|
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, SConnection *pCon){
|
|
hdbValue newValue;
|
|
int i, *iData = NULL;
|
|
char *path = NULL;
|
|
|
|
memset(&newValue,0,sizeof(hdbValue));
|
|
GetHipadabaPar(node, &newValue, pCon);
|
|
path = GetHipadabaPath(node);
|
|
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,path, 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 sendZippedData",eError);
|
|
free(path);
|
|
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,path, iData,
|
|
newValue.arrayLength*sizeof(int));
|
|
free(iData);
|
|
break;
|
|
default:
|
|
SCWrite(pCon,"ERROR: zipped writing not supported for this datatype",
|
|
eError);
|
|
free(path);
|
|
return 0;
|
|
}
|
|
free(path);
|
|
ReleaseHdbValue(&newValue);
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------------------------*/
|
|
static int SICSNotifyCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
HdbCBInfo *cbInfo = NULL;
|
|
pDynString printedData = NULL;
|
|
pDynString result = NULL;
|
|
char *pPath = NULL;
|
|
Protocol protocol = normal_protocol;
|
|
int outCode, macro, status;
|
|
char value[80];
|
|
|
|
cbInfo = (HdbCBInfo *)userData;
|
|
pPath = GetHipadabaPath(node);
|
|
result = CreateDynString(128,128);
|
|
if ((protocol = isJSON(cbInfo->pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
|
|
/*
|
|
* we want our notifications to come even when called from a macro
|
|
*/
|
|
macro = SCinMacro(cbInfo->pCon);
|
|
SCsetMacro(cbInfo->pCon,0);
|
|
/**
|
|
* if transfer = zip always transfer data in zipped form
|
|
*/
|
|
if(GetHdbProperty(node,"transfer",value,80) == 1){
|
|
if(strstr(value,"zip") != NULL){
|
|
SCPushContext2(cbInfo->pCon,cbInfo->context);
|
|
status = sendZippedNodeData(node, cbInfo->pCon);
|
|
SCPopContext(cbInfo->pCon);
|
|
SCsetMacro(cbInfo->pCon,macro);
|
|
free(pPath);
|
|
DeleteDynString(result);
|
|
return status;
|
|
}
|
|
}
|
|
if(v.arrayLength < 100){
|
|
printedData = formatValue(v, node);
|
|
if(pPath == NULL || printedData == NULL || result == NULL){
|
|
SCWriteInContext(cbInfo->pCon,"ERROR: out of memory formatting data" ,
|
|
eEvent,cbInfo->context);
|
|
SCsetMacro(cbInfo->pCon,macro);
|
|
/*
|
|
* no need to interrupt something because writing data to a client does
|
|
* not work
|
|
*/
|
|
return 1;
|
|
}
|
|
formatNameValue(protocol, pPath, GetCharArray(printedData), result, v.dataType);
|
|
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
|
outCode,cbInfo->context);
|
|
DeleteDynString(printedData);
|
|
} else {
|
|
formatNameValue(protocol, pPath,"!!datachange!!", result, HIPTEXT);
|
|
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
|
outCode,cbInfo->context);
|
|
}
|
|
SCsetMacro(cbInfo->pCon,macro);
|
|
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);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int TreeChangeCallback(void *userData, void *callData, pHdb node,
|
|
hdbValue v){
|
|
char *path = NULL;
|
|
char buffer[1024];
|
|
pDynString result = NULL;
|
|
Protocol protocol = normal_protocol;
|
|
int 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, v.dataType);
|
|
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);
|
|
}
|
|
/*----------------------------------------------------------------------------------------*/
|
|
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, node);
|
|
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,NULL);
|
|
}
|
|
/*----------------------------------------------------------------------------------------*/
|
|
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);
|
|
|
|
/*
|
|
* 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)));
|
|
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 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){
|
|
if(pCon != NULL){
|
|
SCWrite(pCon,error,eError);
|
|
}
|
|
return 0;
|
|
}
|
|
return status;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static pHdbCallback MakeSICSReadScriptCallback(char *script){
|
|
return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),
|
|
free,-1,NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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,NULL);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
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(MemGenReadCallback, address,
|
|
NULL,-1,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemReadCallback(float *address){
|
|
return MakeHipadabaCallback(MemReadCallback, address,
|
|
NULL,-1,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
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,NULL);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pHdbCallback MakeMemGenSetCallback(void *address){
|
|
return MakeHipadabaCallback(MemSetCallback, address,
|
|
NULL,-1,NULL);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
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,NULL);
|
|
}
|
|
/*============= 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,HCBSET,pHcb);
|
|
|
|
pHcb = MakeSetUpdateCallback();
|
|
if(pHcb == NULL){
|
|
DeleteHipadabaNode(result,NULL);
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(result,HCBSET,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 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); */
|
|
SetHdbProperty(result,"sicscommand",setScript);
|
|
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 support functions ==============================*/
|
|
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;
|
|
CommandList *pCom;
|
|
pDummy pDum;
|
|
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 >= 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 */
|
|
|
|
pCom = FindCommand(pServ->pSics, element);
|
|
if (pCom == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: object %s not found", element);
|
|
return NULL;
|
|
}
|
|
pDum = pCom->pData;
|
|
if (pDum == NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: object %s has no data", element);
|
|
return NULL;
|
|
}
|
|
node = pDum->pDescriptor->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);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen) {
|
|
pHdb node, parent;
|
|
int len, pos, l;
|
|
static char *sics="/sics";
|
|
CommandList *pCom;
|
|
pDummy pDum;
|
|
|
|
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 >= pathlen) return 0; /* buffer overflow (recursive path?) */
|
|
parent = node;
|
|
}
|
|
|
|
/* check root and add prefix */
|
|
if (parent->mama != root) { /* not anchored in root */
|
|
pCom = FindCommand(pServ->pSics, parent->name);
|
|
if (!pCom) {
|
|
return 0; /* not a sics object */
|
|
}
|
|
pDum = pCom->pData;
|
|
if (pDum->pDescriptor->parNode != parent) {
|
|
/* node named as a sics object, but command is not related to node */
|
|
return 0;
|
|
}
|
|
l= strlen(sics);
|
|
len += l;
|
|
if (len > 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;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int RemoveParNodeCallback(char *name, pDummy object, void *internalID) {
|
|
if (object->pDescriptor->parNode) {
|
|
InternalRemoveHipadabaCallback(object->pDescriptor->parNode, internalID);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void RemoveSICSInternalCallback(void *internalID) {
|
|
InternalRemoveHipadabaCallback(GetHipadabaRoot(), internalID);
|
|
ForEachCommand(RemoveParNodeCallback, internalID);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
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, 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){
|
|
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)){
|
|
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;
|
|
}
|
|
switch(v.dataType){
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
snprintf(number,30,"%d", v.v.intValue);
|
|
DynStringCopy(result,number);
|
|
break;
|
|
case HIPFLOAT:
|
|
if (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 (!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;
|
|
}
|
|
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;
|
|
CommandList *pCom = 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;
|
|
case HIPOBJ:
|
|
pCom = FindCommand(pServ->pSics,data);
|
|
if(pCom == NULL && pCom->pData != NULL){
|
|
snprintf(error,errlen,"object %s NOT found", data);
|
|
return 0;
|
|
}
|
|
v->v.obj = pCom->pData;
|
|
break;
|
|
case HIPFUNC:
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
/*================ 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(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 *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
|
|
*/
|
|
strtolower(argv[3]);
|
|
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[3]);
|
|
}
|
|
}
|
|
|
|
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->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 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 = FindHdbNode(NULL,argv[1],pCon);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
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;
|
|
}
|
|
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 = FindHdbNode(NULL,argv[1],pCon);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
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;
|
|
}
|
|
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);
|
|
} else {
|
|
memset(&newValue,0,sizeof(hdbValue));
|
|
GetHipadabaPar(targetNode,&newValue,pCon);
|
|
}
|
|
status = UpdateHipadabaPar(targetNode,newValue,pCon);
|
|
ReleaseHdbValue(&newValue);
|
|
if(status == 1){
|
|
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;
|
|
|
|
if(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path to node",eError);
|
|
return 0;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
targetNode = FindHdbNode(NULL,argv[1],pCon);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
return sendZippedNodeData(targetNode,pCon);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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(argc < 2) {
|
|
SCWrite(pCon,"ERROR: need path to node to print",eError);
|
|
return 0;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
targetNode = FindHdbNode(NULL,argv[1],pCon);
|
|
if(targetNode == NULL){
|
|
return 0;
|
|
}
|
|
/*
|
|
* if transfer = zip, redirect to zip
|
|
*/
|
|
if(GetHdbProperty(targetNode,"transfer", value,80) == 1){
|
|
if(strstr(value,"zip") != NULL){
|
|
return ZipGetHdbNode(pCon,pSics,pData,argc,argv);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
if ((protocol = isJSON(pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
|
|
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;
|
|
}
|
|
|
|
strncpy(oriPath,argv[1], 511);
|
|
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;
|
|
} else {
|
|
if ((protocol = isJSON(pCon)) == 1)
|
|
outCode = eHdbEvent;
|
|
else
|
|
outCode = eEvent;
|
|
SCWrite(pCon,GetCharArray(parData), outCode);
|
|
DeleteDynString(parData);
|
|
ReleaseHdbValue(&newValue);
|
|
return 1;
|
|
}
|
|
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 = 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->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, current);
|
|
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, 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(strchr(argv[1],'-') != NULL){
|
|
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;
|
|
}
|
|
|
|
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 = FindHdbNode(NULL,argv[1],pCon);
|
|
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){
|
|
memset(&vv,0,sizeof(hdbValue));
|
|
GetHipadabaPar(slave,&vv,callData);
|
|
UpdateHipadabaPar(slave, vv, callData);
|
|
ReleaseHdbValue(&vv);
|
|
}
|
|
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,NULL);
|
|
if(kalle == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory creating callback",eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(master,HCBUPDATE, 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;
|
|
self->parameterChange = 0;
|
|
/*
|
|
get first word of command
|
|
*/
|
|
iRet = InterpExecute(pInter,self,pCommand);
|
|
if(self->parameterChange == 1)
|
|
{
|
|
/*
|
|
automatically save changed parameters
|
|
*/
|
|
pFile = IFindOption(pSICSOptions,"statusfile");
|
|
if(pFile != NULL)
|
|
{
|
|
WriteSicsStatus(pInter,pFile,0);
|
|
self->parameterChange = 0;
|
|
}
|
|
}
|
|
self->inUse--;
|
|
return iRet;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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, current);
|
|
if(par != NULL){
|
|
DynStringConcat(cmd, GetCharArray(par));
|
|
DynStringConcat(cmd," ");
|
|
DeleteDynString(par);
|
|
}
|
|
current = current->next;
|
|
}
|
|
status = HDBInvoke(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 *name = 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;
|
|
}
|
|
|
|
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]);
|
|
|
|
kalle = MakeHipadabaCallback(CommandSetCallback,NULL, NULL, -1,NULL);
|
|
if(kalle == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory in hcommand",eError);
|
|
return 0;
|
|
}
|
|
AppendHipadabaCallback(node,HCBSET, kalle);
|
|
|
|
kalle = MakeHipadabaCallback(CommandGetCallback,NULL, NULL, -1,NULL);
|
|
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 = FindHdbNode(NULL,argv[1],pCon);
|
|
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 = FindHdbNode(NULL,argv[1],pCon);
|
|
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 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 key as parameters",eError);
|
|
return 0;
|
|
}
|
|
targetNode = FindHdbNode(NULL,argv[1],pCon);
|
|
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", 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 = 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);
|
|
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,"hval", GetHdbVal, 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,"hgetpropval",GetSICSHdbPropertyVal, NULL, NULL);
|
|
AddCommand(pSics,"hlistprop",ListSICSHdbProperty, NULL, NULL);
|
|
|
|
InstallSICSPoll(pCon,pSics,pData,argc,argv);
|
|
poller = (pSicsPoll)FindCommandData(pSics,"sicspoll","SicsPoll");
|
|
|
|
return 1;
|
|
}
|