/** * This is a set of helper functions for SICS to work with the hierarchical parameter * database hipadaba. In SICS, the calldata associated with any callback will always * be the connection object. * * copyright: GPL * * Mark Koennecke, June 2006 * * Introduced notification on tree changes, Mark Koennecke, November 2006 * * Added property functions, Mark Koennecke, January 2007 * * Added hmatchprop function. Mark Koennecke, February 2008 * * TODO: separate this into two modules: sicshipadaba proper and sicshipadabaint for the * interpreter interface. * * Refactored to new callback system, Markus Zolliker, Mark Koennecke, March 2008 */ #include #include #include #include #include #include #include "sicspoll.h" #include #include #include "protocol.h" #include "statusfile.h" #include #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); /*====================== Messages ==================================================*/ static char killID[] = {"killID"}; static char killInternalID[] = {"killInternalID"}; static char killPtr[] = {"killPtr"}; /*----------------------------------------------------------------------------------*/ pHdbIDMessage GetKillIDMessage(pHdbMessage message){ if(message->type == killID){ return (pHdbIDMessage)message; } return NULL; } /*-----------------------------------------------------------------------------------*/ pHdbIDMessage GetKillInternalIDMessage(pHdbMessage message){ if(message->type == killInternalID){ return (pHdbIDMessage)message; } return NULL; } /*-----------------------------------------------------------------------------------*/ pHdbPtrMessage GetKillPtrMessage(pHdbMessage message){ if(message->type == killPtr){ return (pHdbPtrMessage)message; } return NULL; } /*=============== common callback functions used for SICS ===========================*/ static hdbCallbackReturn SICSCheckPermissionCallback(pHdb node, void *userData, pHdbMessage message){ int *testPriv = NULL; SConnection *pCon = NULL; pHdbDataMessage mm = NULL; testPriv = (int *)userData; mm = GetHdbSetMessage(message); if(mm == NULL){ return hdbContinue; } pCon = (SConnection *)mm->callData; /* * If pCon is NULL, then this is an internal call from some driver * code where no permission check is necessary. However, when called * through the hipadaba tree commands and other upper level code, the * check will be honoured. */ if(pCon == NULL){ return hdbContinue; } assert(testPriv != NULL); if(SCMatchRights(pCon,*testPriv) == 1){ return hdbContinue; } else { return hdbAbort; } } /*--------------------------------------------------------------------------------------*/ pHdbCallback MakeCheckPermissionCallback(int priv){ int *testPriv = NULL; testPriv = malloc(sizeof(int)); if(testPriv == NULL){ return NULL; } *testPriv = priv; return MakeHipadabaCallback(SICSCheckPermissionCallback, testPriv,free); } /*-------------------------------------------------------------------------------------*/ static char *removeSetUpdateID = "removeSetUpdate"; void RemoveSetUpdateCallback(pHdb node) { hdbPtrMessage m; m.type = killPtr; m.pPtr = removeSetUpdateID; InvokeCallbackChain(node, (pHdbMessage)&m); } /*-------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSSetUpdateCallback(pHdb node, void *userData, pHdbMessage message){ pHdbDataMessage mm = NULL; pHdbPtrMessage pm = NULL; int status; pm = GetKillPtrMessage(message); if (pm != NULL) { if (pm->pPtr == removeSetUpdateID) { return hdbKill; } return hdbContinue; } mm = GetHdbSetMessage(message); if(mm == NULL){ return hdbContinue; } status = UpdateHipadabaPar(node,*(mm->v),mm->callData); if (status) { SCSendOK(mm->callData); } return hdbContinue; } /*-------------------------------------------------------------------------------------*/ pHdbCallback MakeSetUpdateCallback(){ return MakeHipadabaCallback(SICSSetUpdateCallback, NULL,NULL); } /*---------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSReadOnlyCallback(pHdb node, void *userData, pHdbMessage message){ SConnection *pCon = NULL; pHdbDataMessage mm = NULL; mm = GetHdbSetMessage(message); if(mm == NULL){ return hdbContinue; } pCon = (SConnection *)mm->callData; if(pCon != NULL){ SCWrite(pCon,"ERROR: parameter is READ-ONLY", eError); } return hdbAbort; } /*-------------------------------------------------------------------------------------*/ pHdbCallback MakeReadOnlyCallback(){ return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL); } /*-------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSDriveCallback(pHdb node, void *userData, pHdbMessage message){ SConnection *pCon = NULL; pDummy dum = NULL; char pSicsdev[80]; int status; pHdbDataMessage mm = NULL; hdbValue v; mm = GetHdbSetMessage(message); if(mm == NULL){ return hdbContinue; } pCon = (SConnection *)mm->callData; v = *(mm->v); dum = (pDummy)userData; assert(pCon != NULL && dum != NULL); if(GetHdbProperty(node,"sicsdev",pSicsdev,79)){ status = StartDevice(pServ->pExecutor,pSicsdev,dum->pDescriptor, userData, pCon, (float)v.v.doubleValue); } else { status = StartDevice(pServ->pExecutor,node->name,dum->pDescriptor, userData, pCon, (float)v.v.doubleValue); } if(status == 1){ return hdbContinue; } else { return hdbAbort; } } /*---------------------------------------------------------------------------------------*/ pHdbCallback MakeSICSDriveCallback(void *sicsObject){ return MakeHipadabaCallback(SICSDriveCallback, sicsObject,NULL); } /*---------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSReadDriveCallback(pHdb node, void *userData, pHdbMessage message){ static SConnection *defCon = NULL; SConnection *pCon = NULL; pDummy dum = NULL; pIDrivable pDriv = NULL; float value; pHdbDataMessage mm = NULL; mm = GetHdbGetMessage(message); if(mm == NULL){ return hdbContinue; } pCon = (SConnection *)mm->callData; dum = (pDummy)userData; assert(dum != NULL); if(defCon == NULL){ defCon = SCCreateDummyConnection(pServ->pSics); } pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID); assert(pDriv != NULL); if(pCon != NULL){ value = pDriv->GetValue(dum,pCon); node->value.v.doubleValue = (double)value; mm->v->v.doubleValue = (double)value; } else { if(defCon != NULL){ value = pDriv->GetValue(dum,defCon); node->value.v.doubleValue = (double)value; mm->v->v.doubleValue = (double)value; } } return hdbContinue; } /*--------------------------------------------------------------------------*/ static hdbCallbackReturn SICSFuncCallback(pHdb node, void *userData, pHdbMessage message){ pHdb par[64], current = NULL; int nPar = 0; SICSOBJFunc func = NULL; pHdbDataMessage mm = NULL; int status; mm = GetHdbSetMessage(message); if(mm == NULL){ return hdbContinue; } assert(node->value.dataType == HIPFUNC); if(userData == NULL || mm->callData == NULL){ printf("Great Badness in calling SICSFuncCallback\n"); return hdbAbort; } current = node->child; while(current != NULL){ par[nPar] = current; nPar++; current = current->next; } func = (SICSOBJFunc)node->value.v.func; if(func != NULL){ status = func((pSICSOBJ)userData,(SConnection *)mm->callData, node, par,nPar); } else { printf("Great Badness in calling SICSFuncCallback\n"); return hdbAbort; } if(status == 1){ return hdbContinue; } else { return hdbAbort; } } /*---------------------------------------------------------------------------*/ pHdbCallback MakeSICSFuncCallback(void *obj){ return MakeHipadabaCallback(SICSFuncCallback, obj,NULL); } /*--------------------------------------------------------------------------------------*/ pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){ return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject,NULL); } /*---------------------------------------------------------------------------------------*/ typedef struct { SConnection *pCon; commandContext context; int ID; int internalID; }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; newValue = node->value; path = GetHipadabaPath(node); switch(newValue.dataType){ case HIPINTAR: case HIPINTVARAR: if(newValue.v.intArray == NULL){ free(path); return 0; } iData = (int *)malloc(newValue.arrayLength*sizeof(int)); if(iData == NULL){ SCWrite(pCon,"ERROR: out of memory in sendZippedData",eError); free(path); return 0; } memset(iData,0,newValue.arrayLength*sizeof(int)); for(i = 0; i < newValue.arrayLength; i++){ iData[i] = htonl(newValue.v.intArray[i]); } SCWriteZipped(pCon,path, iData, newValue.arrayLength*sizeof(int)); free(iData); break; case HIPFLOATAR: case HIPFLOATVARAR: if(newValue.v.floatArray == NULL){ free(path); return 0; } iData = (int *)malloc(newValue.arrayLength*sizeof(int)); if(iData == NULL){ SCWrite(pCon,"ERROR: out of memory in sendZippedData",eError); free(path); return 0; } memset(iData,0,newValue.arrayLength*sizeof(int)); for(i = 0; i < newValue.arrayLength; i++){ 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); return 1; } /*----------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, pHdbMessage message ){ HdbCBInfo *cbInfo = NULL; pDynString printedData = NULL; pDynString result = NULL; char *pPath = NULL; Protocol protocol = normal_protocol; int outCode, macro, status; char value[80]; pHdbIDMessage idm = NULL; pHdbPtrMessage cmm = NULL; pHdbDataMessage mm = NULL; cbInfo = (HdbCBInfo *)userData; /* * handle kills first */ if((idm = GetKillIDMessage(message)) != NULL){ if(idm->ID == cbInfo->ID){ return hdbKill; } else { return hdbContinue; } } if((idm = GetKillInternalIDMessage(message)) != NULL){ if(idm->ID == cbInfo->internalID){ return hdbKill; } else { return hdbContinue; } } if((cmm = GetKillPtrMessage(message)) != NULL){ if(cmm->pPtr == cbInfo->pCon){ return hdbKill; } else { return hdbContinue; } } /* * react only on update messages */ if((mm = GetHdbUpdateMessage(message)) == NULL){ return hdbContinue; } 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 hdbContinue; } } if(mm->v->arrayLength < 100){ printedData = formatValue(*(mm->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 hdbContinue; } formatNameValue(protocol, pPath, GetCharArray(printedData), result, mm->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 hdbContinue; } /*-----------------------------------------------------------------------------------------*/ 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); cbInfo->ID = id; cbInfo->internalID = -1; return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free); } /*-------------------------------------------------------------------------*/ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, pHdbMessage message){ char *path = NULL; char buffer[1024]; pDynString result = NULL; Protocol protocol = normal_protocol; int outCode; pHdbIDMessage idm = NULL; pHdbPtrMessage cmm = NULL; pHdbTreeChangeMessage tm = NULL; HdbCBInfo *cbInfo = (HdbCBInfo *)userData; /* * handle kills first */ if((idm = GetKillIDMessage(message)) != NULL){ if(idm->ID == cbInfo->ID){ return hdbKill; } else { return hdbContinue; } } if((idm = GetKillInternalIDMessage(message)) != NULL){ if(idm->ID == cbInfo->internalID){ return hdbKill; } else { return hdbContinue; } } if((cmm = GetKillPtrMessage(message)) != NULL){ if(cmm->pPtr == cbInfo->pCon){ return hdbKill; } else { return hdbContinue; } } if((tm = GetHdbTreeChangeMessage(message)) == NULL){ return hdbContinue; } if(cbInfo != NULL && cbInfo->pCon != NULL){ result = CreateDynString(128,128); if(result == NULL){ SCWriteInContext(cbInfo->pCon,"ERROR: out of memory in TreeChangeCallback",outCode,cbInfo->context); return hdbAbort; } path = GetHipadabaPath(node); if ((protocol = isJSON(cbInfo->pCon)) == 1) outCode = eHdbEvent; else outCode = eEvent; formatNameValue(protocol, "treechange", path, result, node->value.dataType); SCWriteInContext(cbInfo->pCon,GetCharArray(result),outCode,cbInfo->context); DeleteDynString(result); free(path); } return hdbContinue; } /*-------------------------------------------------------------------------*/ pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){ HdbCBInfo *cbInfo = NULL; cbInfo = malloc(sizeof(HdbCBInfo)); if(cbInfo == NULL){ return NULL; } cbInfo->pCon = pCon; cbInfo->context = SCGetContext(pCon); cbInfo->ID = id; return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free); } /*----------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSScriptWriteCallback(pHdb node, void *userData, pHdbMessage message){ char *command = NULL; SConnection *pCon = NULL; pDynString newVal = NULL; char error[1024]; int status; pHdbDataMessage mm = NULL; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } command = (char *)userData; pCon = (SConnection *)mm->callData; assert(command != NULL && pCon != NULL); newVal = formatValue(*(mm->v), node); if(newVal == NULL){ SCWrite(pCon,"ERROR: out of memory setting parameter",eError); return hdbAbort; } /** * prepend command */ DynStringInsert(newVal," ", 0); DynStringInsert(newVal,command,0); /* * evaluate */ status = Tcl_Eval(InterpGetTcl(pServ->pSics),GetCharArray(newVal)); if(status != TCL_OK){ snprintf(error,1023,"ERROR: tcl returned error: %s", Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); SCWrite(pCon,error,eError); status = 0; } else { status = 1; } DeleteDynString(newVal); if(status == 1){ return hdbContinue; } else{ return hdbAbort; } } /*---------------------------------------------------------------------------------------*/ static pHdbCallback MakeSICSWriteScriptCallback(char *script){ return MakeHipadabaCallback(SICSScriptWriteCallback, strdup(script),free); } /*----------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSScriptReadCallback(pHdb node, void *userData, pHdbMessage message){ char *command = NULL, *data = NULL, *equal = NULL; SConnection *pCon = NULL; pDynString newVal = NULL; char error[1024]; int status; pHdbDataMessage mm = NULL; if((mm = GetHdbGetMessage(message)) == NULL){ return hdbContinue; } command = (char *)userData; pCon = (SConnection *)mm->callData; assert(command != NULL); /* * evaluate */ 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 hdbAbort; } equal = strchr(data,'='); if(equal != NULL){ data = equal + 1; } strcpy(error,"ERROR: "); status = readHdbValue(&node->value,data, error+7, 1024-7); if(status != 1){ if(pCon != NULL){ SCWrite(pCon,error,eError); } return hdbAbort; } if(status == 1){ return hdbContinue; } else { return hdbAbort; } } /*----------------------------------------------------------------------------*/ static pHdbCallback MakeSICSReadScriptCallback(char *script){ return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script), free); } /*---------------------------------------------------------------------------*/ typedef struct { int min; int max; }hdbIntRange, *pHdbIntRange; /*---------------------------------------------------------------------------*/ static hdbCallbackReturn SICSIntRangeCallback(pHdb node, void *userData, pHdbMessage message){ char buffer[256]; pHdbIntRange range = NULL; SConnection *pCon = NULL; int status = 1; pHdbDataMessage mm = NULL; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } range = (pHdbIntRange)userData; pCon = (SConnection *)mm->callData; assert(range != NULL); if(mm->v->v.intValue > range->max || mm->v->v.intValue < range->min) { status = SICSCBRANGE; if(pCon != NULL){ snprintf(buffer,255,"ERROR: %d is not within permitted range: %d to %d", (int)mm->v->v.intValue, range->min, range->max); SCWrite(pCon,buffer,eError); } return hdbAbort; } return hdbContinue; } /*---------------------------------------------------------------------------*/ pHdbCallback MakeIntRangeCallback(int min, int max){ pHdbIntRange range = NULL; range = malloc(sizeof(hdbIntRange)); if(range == NULL){ return NULL; } range->min = min; range->max = max; return MakeHipadabaCallback(SICSIntRangeCallback, range, free); } /*---------------------------------------------------------------------------*/ typedef struct { double min; double max; }hdbFloatRange, *pHdbFloatRange; /*---------------------------------------------------------------------------*/ static hdbCallbackReturn SICSFloatRangeCallback(pHdb node, void *userData, pHdbMessage message){ char buffer[256]; pHdbFloatRange range = NULL; SConnection *pCon = NULL; int status = 1; pHdbDataMessage mm = NULL; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } range = (pHdbFloatRange)userData; pCon = (SConnection *)mm->callData; assert(range != NULL); if(mm->v->v.doubleValue > range->max || mm->v->v.doubleValue < range->min) { status = SICSCBRANGE; if(pCon != NULL){ snprintf(buffer,255,"ERROR: %lf is not within permitted range: %lf to %lf", mm->v->v.doubleValue, range->min, range->max); SCWrite(pCon,buffer,eError); } return hdbAbort; } return hdbContinue; } /*---------------------------------------------------------------------------*/ pHdbCallback MakeFloatRangeCallback(double min, double max){ pHdbFloatRange range = NULL; range = malloc(sizeof(hdbFloatRange)); if(range == NULL){ return NULL; } range->min = min; range->max = max; return MakeHipadabaCallback(SICSFloatRangeCallback, range, free); } /*------------------------------------------------------------------------*/ static hdbCallbackReturn MemGenReadCallback(pHdb node, void *userData, pHdbMessage message){ pHdbDataMessage mm = NULL; if((mm = GetHdbGetMessage(message)) == NULL){ return hdbContinue; } switch(node->value.dataType){ case HIPINT: node->value.v.intValue = *(int *)userData; break; case HIPFLOAT: node->value.v.doubleValue = *(double *)userData; break; case HIPTEXT: if(node->value.v.text != NULL){ free(node->value.v.text); } node->value.v.text = strdup((char *)userData); break; case HIPINTAR: memcpy(&node->value.v.intArray,userData, node->value.arrayLength *sizeof(int)); break; case HIPFLOATAR: memcpy(&node->value.v.floatArray,userData, node->value.arrayLength *sizeof(double)); break; default: assert(0); break; } return hdbContinue; } /*-------------------------------------------------------------------------*/ pHdbCallback MakeMemGenReadCallback(void *address){ return MakeHipadabaCallback(MemGenReadCallback, address, NULL); } /*-------------------------------------------------------------------------*/ static hdbCallbackReturn MemGenSetCallback(pHdb node, void *userData, pHdbMessage message){ const char *pPtr = NULL; pHdbDataMessage mm = NULL; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } if(mm->v->dataType != node->value.dataType){ assert(0); return 0; } switch(node->value.dataType){ case HIPINT: memcpy(userData,&mm->v->v.intValue,sizeof(int)); break; case HIPFLOAT: memcpy(userData,&mm->v->v.doubleValue,sizeof(double)); break; case HIPTEXT: strncpy((char *)userData,(const char *)mm->v->v.text, node->value.arrayLength); break; case HIPINTAR: memcpy(userData,&mm->v->v.intArray,node->value.arrayLength*sizeof(int)); break; case HIPFLOATAR: memcpy(userData,&mm->v->v.floatArray, node->value.arrayLength*sizeof(double)); break; default: assert(0); return 0; break; } UpdateHipadabaPar(node,*(mm->v),mm->callData); return hdbContinue; } /*-------------------------------------------------------------------------*/ pHdbCallback MakeMemGenSetCallback(void *address){ return MakeHipadabaCallback(MemGenSetCallback, address, NULL); } /*--------------------------------------------------------------------------*/ static void killHdbValue(void *pData){ hdbValue *v = NULL; v = (hdbValue *)pData; if(v == NULL){ return; } ReleaseHdbValue(v); free(v); } /*--------------------------------------------------------------------------*/ static hdbCallbackReturn SICSIntFixedCallback(pHdb node, void *userData, pHdbMessage message){ hdbValue *allowed = NULL; SConnection *pCon = NULL; int i; pHdbDataMessage mm = NULL; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } allowed = (hdbValue *)userData; pCon = (SConnection *)mm->callData; assert(allowed != NULL && allowed->dataType == HIPINTAR); for(i = 0; i < allowed->arrayLength; i++){ if(mm->v->v.intValue == allowed->v.intArray[i]){ return hdbContinue; } } if(pCon != NULL){ SCWrite(pCon,"ERROR: value is not in the list of allowed values",eError); } return hdbAbort; } /*---------------------------------------------------------------------------*/ pHdbCallback MakeIntFixedCallback(int *data, int length){ pHdbCallback result = NULL; hdbValue *v = NULL; v = malloc(sizeof(hdbValue)); if(v == NULL){ return NULL; } v->dataType = HIPINTAR; v->arrayLength = length; v->v.intArray = malloc(length*sizeof(int)); if(v->v.intArray == NULL){ return NULL; } memcpy(v->v.intArray,data,length*sizeof(int)); return MakeHipadabaCallback(SICSIntFixedCallback, v, killHdbValue); } /*============= Parameter Creation ===========================================*/ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){ pHdb result = NULL; pHdbCallback pHcb = NULL; char pPriv[20]; result = MakeHipadabaNode(name,v.dataType,v.arrayLength); if(result == NULL){ return NULL; } copyHdbValue(&v,&result->value); pHcb = MakeCheckPermissionCallback(priv); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeSetUpdateCallback(); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); switch(priv){ case 0: strcpy(pPriv,"internal"); break; case 1: strcpy(pPriv,"manager"); break; case 2: strcpy(pPriv,"user"); break; case 3: strcpy(pPriv,"spy"); break; } SetHdbProperty(result,"priv",pPriv); return result; } /*----------------------------------------------------------------------------*/ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){ pHdb result = NULL; pHdbCallback pHcb = NULL; result = MakeHipadabaNode(name,dataType,0); if(result == NULL){ return NULL; } pHcb = MakeCheckPermissionCallback(priv); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeSICSDriveCallback(sicsObject); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeSICSReadDriveCallback(sicsObject); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); return result; } /*---------------------------------------------------------------------------*/ pHdb MakeSICSMemPar(char *name, int priv, float *address){ pHdb result = NULL; pHdbCallback pHcb = NULL; result = MakeHipadabaNode(name,HIPFLOAT,1); if(result == NULL){ return NULL; } pHcb = MakeCheckPermissionCallback(priv); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeMemGenSetCallback(address); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeMemGenReadCallback(address); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); return result; } /*----------------------------------------------------------------------------*/ pHdb MakeSICSROPar(char *name, hdbValue v){ pHdb result = NULL; pHdbCallback pHcb = NULL; result = MakeHipadabaNode(name,v.dataType,v.arrayLength); if(result == NULL){ return NULL; } copyHdbValue(&v,&result->value); pHcb = MakeReadOnlyCallback(); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); return result; } /*---------------------------------------------------------------------------*/ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, hdbValue v){ pHdb result = NULL; pHdbCallback pHcb = NULL; result = MakeHipadabaNode(name,v.dataType,v.arrayLength); if(result == NULL){ return NULL; } copyHdbValue(&v,&result->value); pHcb = MakeSICSWriteScriptCallback(setScript); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); pHcb = MakeSICSReadScriptCallback(readScript); if(pHcb == NULL){ DeleteHipadabaNode(result,NULL); return NULL; } AppendHipadabaCallback(result,pHcb); /** * put into the list of nodes to check with the update task */ /* LLDnodeAppend(scriptUpdate,&result); */ SetHdbProperty(result,"sicscommand",setScript); return result; } /*--------------------------------------------------------------------------*/ static void removeNodeFromUpdateList(pHdb node){ pHdb current = NULL; int status; char *objName = NULL; objName = GetHipadabaPath(node); if(objName != NULL){ removePollObject(poller, objName); free(objName); } } /*-----------------------------------------------------------------------*/ static void SICSDeleteNodeData(pHdb node){ pHdb tmp = NULL; if(node == NULL){ return; } removeNodeFromUpdateList(node); while(node->child != NULL){ tmp = node->child; node->child = node->child->next; SICSDeleteNodeData(tmp); } if(node->properties != NULL){ DeleteStringDict(node->properties); } DeleteCallbackChain(node->callBackChain); if(node->name != NULL){ free(node->name); } ReleaseHdbValue(&node->value); node->magic = 000000; free(node); } /*--------------------------------------------------------------------------*/ void RemoveSICSPar(pHdb node, void *callData){ pHdb current = NULL, tmp = NULL; if(node == NULL){ return; } RemoveHdbNodeFromParent(node,NULL); SICSDeleteNodeData(node); } /*===================== add functions =======================================*/ pHdb AddSICSHdbPar(pHdb parent, char *name, int priv, hdbValue v){ pHdb child = NULL; child = MakeSICSHdbPar(name,priv,v); if(child != NULL){ AddHipadabaChild(parent,child,NULL); } return child; } /*---------------------------------------------------------------------------*/ pHdb AddSICSHdbROPar(pHdb parent, char *name, hdbValue v){ pHdb child = NULL; child = MakeSICSROPar(name,v); if(child != NULL){ AddHipadabaChild(parent,child,NULL); } return child; } /*--------------------------------------------------------------------------*/ pHdb AddSICSHdbMemPar(pHdb parent, char *name, int priv, void *data, int datalength, int type, int length){ pHdb child = NULL; pHdbCallback pHcb = NULL; if(type == HIPINTVARAR || type == HIPFLOATVARAR){ assert(0); return NULL; } child = MakeHipadabaNode(name,type,length); if(child == NULL){ return NULL; } pHcb = MakeCheckPermissionCallback(priv); if(pHcb == NULL){ DeleteHipadabaNode(child,NULL); return NULL; } AppendHipadabaCallback(child,pHcb); pHcb = MakeMemGenSetCallback(data); if(pHcb == NULL){ DeleteHipadabaNode(child,NULL); return NULL; } AppendHipadabaCallback(child,pHcb); pHcb = MakeMemGenReadCallback(data); if(pHcb == NULL){ DeleteHipadabaNode(child,NULL); return NULL; } AppendHipadabaCallback(child,pHcb); AddHipadabaChild(parent,child,NULL); return child; } /*==================== access support functions ==============================*/ pHdb FindHdbParent(char *rootpath, char *relpath, char **namePtr, SConnection *pCon) { /* for namePtr == NULL, implements also "find node" */ char *element; char buffer[MAX_HDB_PATH]; pHdb node = NULL; pHdb parent = NULL; char *name; char *slash; pObjectDescriptor pDes; int iret; if (relpath[0] == '/' || rootpath == NULL) { /* absolute path */ iret = snprintf(buffer, sizeof buffer, "%s", relpath); } else { iret = snprintf(buffer, sizeof buffer, "%s/%s", rootpath, relpath); } if (iret < 0 || iret >= sizeof(buffer)) { SCWrite(pCon,"ERROR: path too long",eError); return NULL; } element = buffer; if (strncmp(element, "/sics/", 6) == 0) { /* sics object case */ slash = strchr(element+6, '/'); if (slash != NULL) *slash = '\0'; /* split off object name */ pDes = FindCommandDescriptor(pServ->pSics, element+6); if (pDes == NULL) { SCPrintf(pCon, eError, "ERROR: object %s not found", element); return NULL; } node = pDes->parNode; if (node == NULL) { SCPrintf(pCon, eError, "ERROR: object %s does not use hipadaba", element); return NULL; } if (slash == NULL) goto nodeFound; *slash = '/'; element = slash+1; parent = node; /* parent is sics object, path is relative to it */ } else { /* normal path */ parent = GetHipadabaRoot(); } while (1) { slash = strchr(element, '/'); if (slash != NULL) *slash = '\0'; /* split off next path element */ if (strcmp(element, "") == 0 || strcmp(element, ".") == 0) { /* cases "//" and "/./" : do not move in tree */ if (slash == NULL) { node = parent; goto nodeFound; } *slash = '/'; element = slash + 1; } else { for (node = parent->child; node != NULL; node = node->next) { if (strcasecmp(element, node->name) == 0) { break; } } if (node == NULL) { if (namePtr) { /* "find parent" case */ if (slash != NULL) { /* element is not the last in path */ *slash = '/'; SCPrintf(pCon, eError, "ERROR: parent of %s not found", buffer); return NULL; } /* the name must be taken from the end of relpath, as element is no longer valid */ *namePtr = relpath + (element - buffer); return parent; /* parent found, and node does not yet exist */ } /* "find node" case */ if (slash != NULL) *slash = '/'; SCPrintf(pCon, eError, "ERROR: node %s not found", buffer); return NULL; } /* node found */ if (slash == NULL) goto nodeFound; parent = node; *slash = '/'; element = slash + 1; } } nodeFound: if (namePtr) { /* "find parent" case */ *namePtr = node->name; SCPrintf(pCon, eError, "ERROR: node %s exists already", buffer); return NULL; } return node; /* node found */ } /*--------------------------------------------------------------------------*/ pHdb FindHdbNode(char *rootpath, char *relpath, SConnection *pCon) { return FindHdbParent(rootpath, relpath, NULL, pCon); } /*--------------------------------------------------------------------------*/ int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen) { pHdb node, parent; int len, pos, l; static char *sics="/sics"; pObjectDescriptor pDes; path[0]='\0'; if (nodeArg == NULL) { return 0; } /* determine path length and root node */ parent = nodeArg; len = 0; for (node = nodeArg; node != NULL && node != root; node = node->mama) { len += strlen(node->name) + 1; if (len >= pathlen) return 0; /* buffer overflow (recursive path?) */ parent = node; } /* check root and add prefix */ if (parent->mama != root) { /* not anchored in root */ pDes = FindCommandDescriptor(pServ->pSics, parent->name); if (!pDes) { return 0; /* not a sics object */ } if (pDes->parNode != parent) { /* node named as a sics object, but command is not related to node */ return 0; } l= strlen(sics); len += l; if (len > 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) { hdbPtrMessage m; m.type = killPtr; m.pPtr = internalID; if (object->pDescriptor->parNode) { RecurseCallbackChains(object->pDescriptor->parNode,(pHdbMessage)&m); } return 1; } /*--------------------------------------------------------------------------*/ void RemoveSICSInternalCallback(void *internalID) { hdbPtrMessage m; m.type = killPtr; m.pPtr = internalID; RecurseCallbackChains(GetHipadabaRoot(),(pHdbMessage)&m); ForEachCommand(RemoveParNodeCallback, internalID); } /*--------------------------------------------------------------------------*/ int SICSHdbGetPar(void *obj, SConnection *pCon, char *path, hdbValue *v){ pHdb par = NULL; int status; char buffer[256]; pDummy pDum; pDum = (pDummy)obj; if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } par = GetHipadabaNode(pDum->pDescriptor->parNode,path); if(par == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } status = GetHipadabaPar(par,v,pCon); if(status < 0){ return status; } return 1; } /*--------------------------------------------------------------------------*/ int SICSHdbUpdatePar(void *obj, SConnection *pCon, char *path, hdbValue v){ pHdb par = NULL; int status; char buffer[256]; pDummy pDum; pDum = (pDummy)obj; if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } par = GetHipadabaNode(pDum->pDescriptor->parNode,path); if(par == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } status = UpdateHipadabaPar(par,v,pCon); if(status < 0){ return status; } return 1; } /*--------------------------------------------------------------------------*/ int SICSHdbSetPar(void *obj, SConnection *pCon, char *path, hdbValue v){ pHdb par = NULL; int status; char buffer[256]; pDummy pDum; pDum = (pDummy)obj; if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } par = GetHipadabaNode(pDum->pDescriptor->parNode,path); if(par == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); SCWrite(pCon,buffer,eError); } return SICSNOPAR; } status = SetHipadabaPar(par,v,pCon); if(status <= 0){ return status; } return 1; } /*---------------------------------------------------------------------------*/ int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){ pHdb currentChild = NULL; pHdbCallback noty = NULL; pHdbCallback treeChange = NULL; treeChange = MakeTreeChangeCallback(pCon,id); noty = MakeNotifyCallback(pCon,id); if(noty == NULL || treeChange == NULL){ SCWrite(pCon,"ERROR: out of memory installing callback", eError); return 0; } AppendHipadabaCallback(node, noty); AppendHipadabaCallback(node, treeChange); if(recurse == 1){ currentChild = node->child; while(currentChild != NULL){ InstallSICSNotify(currentChild,pCon,id,recurse); currentChild = currentChild->next; } } return 1; } /*---------------------------------------------------------------------------*/ void RemoveConnectionCallbacks(pHdb root, SConnection *pCon){ hdbPtrMessage dsm; dsm.type = killPtr; dsm.pPtr = pCon; RecurseCallbackChains(root,(pHdbMessage)&dsm); } /*---------------------------------------------------------------------------*/ int ProcessSICSHdbPar(pHdb root, SConnection *pCon, char *printPrefix, int argc, char *argv[]){ hdbValue input; pHdb parNode = NULL; pDynString parData = NULL; char error[512]; int i, status; 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); do not send OK. this has to be done by the callback */ SCparChange(pCon); } return status; } else { /* * reading is in demand */ status = GetHipadabaPar(parNode,&input, pCon); if(status != 1){ return 0; } parData = formatValue(input, parNode); if(parData == NULL){ SCWrite(pCon,"ERROR: out of memory reading parameter data",eError); return 0; } DynStringInsert(parData," = ", 0); DynStringInsert(parData,argv[0],0); if(printPrefix != NULL){ DynStringInsert(parData,printPrefix,0); } SCWrite(pCon,GetCharArray(parData),eValue); DeleteDynString(parData); ReleaseHdbValue(&input); return 1; } } /*--------------------------------------------------------------------------*/ void PrintSICSParList(pHdb node, SConnection *pCon, char *prefix){ char childPrefix[1024]; pHdb child = NULL; pDynString value = NULL; hdbValue v; child = node->child; while(child != NULL){ if(child->value.dataType != HIPNONE){ GetHipadabaPar(child,&v,pCon); value = formatValue(child->value, child); if(value != NULL){ SCPrintf(pCon,eValue,"%s%s = %s", prefix, child->name, GetCharArray(value)); DeleteDynString(value); } } if(child->child != NULL){ 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; void *objData; switch(v->dataType){ case HIPNONE: break; case HIPINT: getNextHdbNumber(data,number); status = sscanf(number,"%d", &v->v.intValue); if(status != 1){ snprintf(error,errlen,"Failed to convert %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: break; case HIPFUNC: break; default: assert(0); break; } return 1; } /*-------------------------------------------------------------------------*/ hdbValue MakeSICSFunc(SICSOBJFunc func) { return MakeHdbFunc((voidFunc *)func); } /*================ interpreter interface ==================================*/ pHdb GetHipadabaRoot(){ return root; } /*-------------------------------------------------------------------------*/ static char *hdbTypes[] = {"none", "int", "float", "text", "intar", "floatar", "intvarar", "floatvarar", "object", "func", NULL}; /*-------------------------------------------------------------------------*/ int convertHdbType(char *text){ int type; type = 0; while(hdbTypes[type] != NULL){ if(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; } DynStringConcat(parData, argv[2]); for(i = 3; i < argc; i++){ DynStringConcat(parData," "); DynStringConcat(parData, argv[i]); } strcpy(error,"ERROR: "); if(!readHdbValue(&newValue, GetCharArray(parData), error+7,512-7)){ SCWrite(pCon,error, eError); return 0; } DeleteDynString(parData); status = SetHipadabaPar(targetNode,newValue,pCon); ReleaseHdbValue(&newValue); if(status == 1){ /* SCSendOK(pCon); sending ok has to be done by the callback. */ } return status; } /*---------------------------------------------------------------------------*/ static int UpdateHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb targetNode = NULL; hdbValue newValue; pDynString parData = NULL; char error[512]; int i, status; /* if(!SCMatchRights(pCon,usUser)){ return 0; } */ if(argc < 2) { SCWrite(pCon,"ERROR: insufficient number of arguments to UpdateHdbNode", eError); return 0; } targetNode = FindHdbNode(NULL,argv[1],pCon); if(targetNode == NULL){ return 0; } 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; hdbValue newValue; 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; } memset(&newValue,0,sizeof(hdbValue)); GetHipadabaPar(targetNode, &newValue, pCon); ReleaseHdbValue(&newValue); 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(strstr(argv[1],"values") != NULL){ printf("Found!!\n"); } */ 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->callBackChain; while(current != NULL){ if(current->userCallback == SICSReadOnlyCallback) { return 1; } current = current->next; } return 0; } /*---------------------------------------------------------------------------*/ static pDynString formatPlainList(pHdb node){ pHdb current; pDynString result = NULL; result = CreateDynString(128,128); if(result == NULL){ return NULL; } current = node->child; while(current != NULL){ DynStringConcat(result,current->name); DynStringConcat(result,"\n"); current = current->next; } return result; } /*---------------------------------------------------------------------------*/ static pDynString formatJSONList(pHdb node){ 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(argv[1][0] == '-'){ pathArg = 2; if(argc < 3){ SCWrite(pCon,"ERROR: need path to node to print",eError); return 0; } } node = FindHdbNode(NULL,argv[pathArg],pCon); if(node == NULL){ return 0; } 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; hdbIDMessage m; if(argc < 2) { SCWrite(pCon,"ERROR: need callback id to remove", eError); return 0; } id = atoi(argv[1]); m.type = killID; m.ID = id; RecurseCallbackChains(root,(pHdbMessage)&m); SCSendOK(pCon); return 1; } /*---------------------------------------------------------------------------*/ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb node = NULL; char buffer[256]; pObjectDescriptor pDes = NULL; if(argc < 3) { SCWrite(pCon,"ERROR: need path and object name to link", eError); return 0; } if(!SCMatchRights(pCon,usMugger)){ return 0; } node = GetHipadabaNode(root,argv[1]); if(node == NULL){ snprintf(buffer,255,"ERROR: path %s NOT found!", argv[1]); SCWrite(pCon,buffer,eError); return 0; } pDes = FindCommandDescriptor(pSics,argv[2]); if(pDes == NULL){ snprintf(buffer,255,"ERROR: failed to find object %s", argv[2]); SCWrite(pCon,buffer,eError); return 0; } if(pDes->parNode == NULL){ snprintf(buffer,255, "ERROR: Object %s does not use Hipadaba natively and thus cannot be linked", argv[2]); SCWrite(pCon,buffer,eError); return 0; } if(pDes->parNode->mama != NULL){ snprintf(buffer,255, "ERROR: Object %s is already linked somewhere else", argv[2]); SCWrite(pCon,buffer,eError); return 0; } AddHipadabaChild(node,pDes->parNode,pCon); if(argc > 3){ if(pDes->parNode->name != NULL){ free(pDes->parNode->name); } pDes->parNode->name = strdup(argv[3]); } SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------------*/ static hdbCallbackReturn ChainCallback(pHdb node, void *userData, pHdbMessage message){ pHdb slave = (pHdb)userData; hdbValue vv, old; pHdbDataMessage mm = NULL; if((mm = GetHdbUpdateMessage(message)) == NULL){ return hdbContinue; } if(slave != NULL){ memset(&vv,0,sizeof(hdbValue)); GetHipadabaPar(slave,&vv,mm->callData); UpdateHipadabaPar(slave, vv, mm->callData); ReleaseHdbValue(&vv); } return hdbContinue; } /*--------------------------------------------------------------------------*/ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb master = NULL, slave = NULL; char buffer[512]; pHdbCallback kalle = NULL; if(argc < 3) { SCWrite(pCon,"ERROR: insufficent number of arguments to hchain", eError); } if(!SCMatchRights(pCon,usMugger)){ return 0; } slave = GetHipadabaNode(root,argv[1]); if(slave == NULL){ snprintf(buffer,511,"ERROR: slave %s not found",argv[1]); SCWrite(pCon,buffer,eError); return 0; } master = GetHipadabaNode(root,argv[2]); if(master == NULL){ snprintf(buffer,511,"ERROR: master %s not found",argv[1]); SCWrite(pCon,buffer,eError); return 0; } kalle = MakeHipadabaCallback(ChainCallback,slave, NULL); if(kalle == NULL){ SCWrite(pCon,"ERROR: out of memory creating callback",eError); return 0; } AppendHipadabaCallback(master,kalle); SCSendOK(pCon); return 1; } /* -------------------------------------------------------------------------- * This is actually SCInvoke but without advancing the context. I think this * is only of local use. It makes sure that commands executed as Hipadaba * commands get logged properly. */ static int HDBInvoke(SConnection *self, SicsInterp *pInter, char *pCommand) { int iRet; long lLen; const char *pResult = NULL; char *pBuffer = NULL, *pFile = NULL; char pBueffel[80]; int i, iSpace; assert(pInter); /* print command to log files */ for( i = 0; i < self->iFiles; i++) { if(self->pFiles[i]) { fprintf(self->pFiles[i],"SICS>> %s\n",pCommand); } } /* print to command log if user or manager */ if(SCGetRights(self) <= usUser) { if(self->pSock != NULL) { sprintf(pBueffel,"sock %d>>",self->pSock->sockid); } } /* invoke */ self->inUse++; self->eInterrupt = eContinue; /* get first word of command */ iRet = InterpExecute(pInter,self,pCommand); StatusFileTask(NULL); /* save changed parameters */ self->inUse--; return iRet; } /*---------------------------------------------------------------------------*/ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData, pHdbMessage message){ SConnection *pCon = NULL; pDynString cmd = NULL, par = NULL; pHdb current = NULL; int status; pHdbDataMessage mm = NULL; hdbValue v; if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } pCon = (SConnection *)pCon; v = *(mm->v); if(pCon == NULL){ printf("Cannot invoke command without connection\n"); return hdbAbort; } if(v.dataType == HIPTEXT){ if(strstr(v.v.text,"start") != NULL) { cmd = CreateDynString(64,64); if(cmd == 0){ SCWrite(pCon,"ERROR: out of memory in CommandSetCallback",eError); return 0; } DynStringCopy(cmd, node->value.v.text); DynStringConcat(cmd," "); current = node->child; while(current != NULL){ par = formatValue(current->value, current); if(par != NULL){ DynStringConcat(cmd, GetCharArray(par)); DynStringConcat(cmd," "); DeleteDynString(par); } current = current->next; } status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd)); DeleteDynString(cmd); if(status == 1){ return hdbContinue; } else { return hdbAbort; } } else { SCWrite(pCon,"ERROR: this node only understands start as value",eError); return hdbAbort; } } return hdbContinue; } /*---------------------------------------------------------------------------*/ static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData, pHdbMessage message){ pHdbDataMessage mm = NULL; if((mm = GetHdbGetMessage(message)) == NULL){ return hdbContinue; } hdbValue v2 = MakeHdbText("Nothing to get"); copyHdbValue(&v2, mm->v); /* MakeHdbText makes no strdup ! */ return hdbContinue; } /*--------------------------------------------------------------------------*/ static int SicsCommandNode(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ char *name = NULL; pHdbCallback kalle = NULL; pHdb parent = NULL, node = NULL; if(argc < 3) { SCWrite(pCon,"ERROR: insufficent number of arguments to hcommand", eError); } 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); if(kalle == NULL){ SCWrite(pCon,"ERROR: out of memory in hcommand",eError); return 0; } AppendHipadabaCallback(node,kalle); kalle = MakeHipadabaCallback(CommandGetCallback,NULL, NULL); if(kalle == NULL){ SCWrite(pCon,"ERROR: out of memory in hcommand",eError); return 0; } AppendHipadabaCallback(node,kalle); AddHipadabaChild(parent,node,pCon); SCSendOK(pCon); return 1; } /*======================= Property Functions ================================*/ static int SetSICSHdbProperty(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb targetNode = NULL; char buffer[512]; char *val; if(argc < 4) { SCWrite(pCon,"ERROR: need path key value as parameters",eError); return 0; } targetNode = FindHdbNode(NULL,argv[1],pCon); if(targetNode == NULL){ SCWrite(pCon,"ERROR: node not found",eError); return 0; } val = Arg2Tcl(argc-3, &argv[3], buffer, sizeof buffer); if (val) { SetHdbProperty(targetNode,argv[2], val); if (val != buffer) free(val); } 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; } /*---------------------------------------------------------------------------*/ static pHdb matchHdbProp(pHdb root, char *propname, char *buffer){ char value[1024]; pHdb current = NULL, search; memset(value,0,1024); if(GetHdbProperty(root,propname,value,1023) == 1){ if(strstr(buffer,value) != NULL){ return root; } } current = root->child; while(current != NULL){ search = matchHdbProp(current,propname,buffer); if(search != NULL){ return search; } current = current->next; } return NULL; } /*---------------------------------------------------------------------------*/ static int MatchHdbProperty(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb root = NULL; pHdb foundNode = NULL; char buffer[1024], *path = NULL; if(argc < 4){ SCWrite(pCon,"ERROR: need root, property name and target string for search", eError); return 0; } memset(buffer,0,1024); Arg2Text(argc-3,&argv[3],buffer,1023); root = GetHipadabaNode(GetHipadabaRoot(), argv[1]); if(root == NULL){ SCWrite(pCon,"ERROR: start node for search not found",eError); return 0; } strtolower(argv[2]); strtolower(buffer); foundNode = matchHdbProp(root,argv[2],buffer); if(foundNode == NULL){ SCWrite(pCon,"NONE", eValue); } else { path = GetHipadabaPath(foundNode); SCWrite(pCon,path,eValue); free(path); } return 1; } /*======================= Factory Functions =================================*/ void killSICSHipadaba(){ if(root != NULL){ DeleteHipadabaNode(root,NULL); } root = NULL; } /*---------------------------------------------------------------------------*/ extern int HdbNodeFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /* from sicshdbfactory.c */ /*---------------------------------------------------------------------------*/ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ root = MakeHipadabaNode("/",HIPNONE,0); AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL); AddCommand(pSics,"hfactory", HdbNodeFactory, NULL, NULL); AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL); AddCommand(pSics,"hattach", SICSHdbAdapter, NULL, NULL); AddCommand(pSics,"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,"hmatchprop",MatchHdbProperty, NULL, NULL); AddCommand(pSics,"hlistprop",ListSICSHdbProperty, NULL, NULL); InstallSICSPoll(pCon,pSics,pData,argc,argv); poller = (pSicsPoll)FindCommandData(pSics,"sicspoll","SicsPoll"); return 1; }