/** * This is the header file for the new (as of 2007) style SICS objects * * copyright: see file COPYRIGHT * * Mark Koennecke, July 2007 */ #include #include #include "assert.h" #include "ifile.h" #include "sicsobj.h" #include "dynstring.h" #include "macro.h" #include "sicshipadaba.h" #include "initializer.h" #include "splitter.h" extern int decodeSICSPriv(char *txt); /* from access.c */ /*--------------------------------------------------------------------------*/ static void DefaultKill(void *data){ return; } /*---------------------------------------------------------------------------*/ pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv){ pSICSOBJ pNew = NULL; hdbValue val; pNew = (pSICSOBJ)malloc(sizeof(SICSOBJ)); if(pNew == NULL){ return NULL; } memset(pNew,0,sizeof(SICSOBJ)); pNew->pDes = CreateDescriptor(class); if (type == HIPNONE) { pNew->objectNode = MakeHipadabaNode(name, HIPNONE, 1); } else { val = makeHdbValue(type,0); pNew->objectNode = MakeSICSHdbPar(name, priv, val); ReleaseHdbValue(&val); } if(pNew->pDes == NULL || pNew->objectNode == NULL){ free(pNew); return(NULL); } pNew->pDes->parNode = pNew->objectNode; pNew->KillPrivate = DefaultKill; return pNew; } /*---------------------------------------------------------------------------*/ pSICSOBJ MakeSICSOBJ(char *name, char *class){ return MakeSICSOBJv(name, class, HIPNONE, 0); } /*---------------------------------------------------------------------------*/ void KillSICSOBJ(void *data){ pSICSOBJ self = (pSICSOBJ)data; if(self == NULL){ return; } if(self->KillPrivate != NULL && self->pPrivate != NULL){ self->KillPrivate(self->pPrivate); } RemoveHdbNodeFromParent(self->objectNode, pServ->dummyCon); if(self->pDes != NULL){ DeleteDescriptor(self->pDes); /* kill descriptor including node */ } free(self); } /*===========================================================================*/ static int assignPar(pHdb node, SConnection *pCon, char *data){ char error[132], buffer[256]; int status; status = readHdbValue(&node->value,data, error, 132); if(status != 1){ snprintf(buffer,255,"ERROR: error parsing %s: %s", node->name, error); SCWrite(pCon,buffer,eError); return 0; } return 1; } /*---------------------------------------------------------------------------*/ static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCon, int argc, char *argv[]){ int status, i, count = 0; pHdb currentPar = NULL; SICSOBJFunc pFunc = NULL; pHdb parArray[64]; /* * assign parameters and fill parameter array for function at the same * time. Be lenient about missing parameters: Then the old values will * be used. */ for(i = 0, currentPar = commandNode->child; i < argc && currentPar != NULL; i++, currentPar = currentPar->next){ if(argv[i] != NULL){ status = assignPar(currentPar,pCon, argv[i]); } if(status != 1){ return status; } parArray[i] = currentPar; count++; } pFunc = (SICSOBJFunc)commandNode->value.v.func; if(pFunc == NULL){ SCWrite(pCon,"ERROR: internal error, function not found",eError); return 0; } status = pFunc(object, pCon, commandNode, parArray,count); return status; } /*---------------------------------------------------------------------------*/ static int ScriptObjFunc(pSICSOBJ obj, SConnection *pCon, pHdb commandNode, pHdb par[], int nCount){ int status, i; Tcl_Interp *pTcl = NULL; Tcl_DString com; char value[256]; pDynString val = NULL; char *pPtr = NULL; memset(value,0,256); GetHdbProperty(commandNode,"priv",value,256); status = decodeSICSPriv(value); if(!SCMatchRights(pCon,status)){ return 0; } if(GetHdbProperty(commandNode,"script",value,256) != 1){ SCWrite(pCon,"ERROR: script property not configured on this node", eError); return 0; } Tcl_DStringInit(&com); Tcl_DStringAppend(&com,value,strlen(value)); for(i = 0; i < nCount; i++){ val = formatValue(par[i]->value, par[i]); if(val != NULL){ Tcl_DStringAppend(&com," ", 1); pPtr = GetCharArray(val); Tcl_DStringAppend(&com,pPtr,strlen(pPtr)); DeleteDynString(val); } } MacroPush(pCon); pTcl = InterpGetTcl(pServ->pSics); status = Tcl_Eval(pTcl,Tcl_DStringValue(&com)); Tcl_DStringFree(&com); MacroPop(); if(status == TCL_OK){ SCWrite(pCon,Tcl_GetStringResult(pTcl),eValue); return 1; } else { SCWrite(pCon,Tcl_GetStringResult(pTcl),eError); return 0; } return 1; } /*--------------------------------------------------------------------------*/ static int MakeScriptFunc(pSICSOBJ self, SConnection *pCon, int argc, char *argv[]){ char path[512], *pPtr = NULL; pHdb parent = NULL, node = NULL; hdbValue func; if(argc < 5){ SCWrite(pCon, "ERROR: not enough arguments: obj makescriptfunc path script priv", eError); return 0; } if(!SCMatchRights(pCon,usMugger)){ return 0; } strncpy(path,argv[2],511); pPtr = strrchr(path,'/'); if(pPtr == NULL){ /* no hierarchy */ parent = self->objectNode; node = MakeHipadabaNode(path,HIPFUNC,1); } else { /* hierarchy */ *pPtr = '\0'; parent = GetHipadabaNode(self->objectNode,path); pPtr++; node = MakeHipadabaNode(pPtr,HIPFUNC,1); } if(parent == NULL || node == NULL){ SCWrite(pCon,"ERROR: root path error or out of memory",eError); return 0; } node->value = MakeSICSFunc(ScriptObjFunc); SetHdbProperty(node,"script",argv[3]); SetHdbProperty(node,"priv",argv[4]); AppendHipadabaCallback(node,MakeSICSFuncCallback(self)); AddHipadabaChild(parent,node,pCon); SCSendOK(pCon); return 1; } /*---------------------------------------------------------------------------*/ int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSOBJ self = NULL; int status; pHdb parNode; char buffer[132]; self = (pSICSOBJ)pData; assert(self != NULL); if(argc < 2){ SCWrite(pCon,"ERROR: Nothing to process",eError); return -1; } if (argc == 1) { parNode = self->objectNode; } else { parNode = GetHipadabaNode(self->objectNode,argv[1]); } if(parNode != NULL && parNode->value.dataType == HIPFUNC){ status = invokeOBJFunction(self, parNode, pCon, argc-2, &argv[2]); } else { snprintf(buffer, sizeof buffer, "%s ", argv[0]); status = ProcessSICSHdbPar(self->objectNode,pCon, buffer, argc-1,&argv[1]); } if(status == -1){ if(strcmp(argv[1],"makescriptfunc") == 0) { return MakeScriptFunc(self,pCon,argc,argv); } } return status; } /*---------------------------------------------------------------------------*/ int InterInvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ int status; char buffer[132]; status = InvokeSICSOBJ(pCon,pSics,pData,argc,argv); if(status == -1){ status = 0; if(argc > 1){ snprintf(buffer,131,"ERROR: no command or parameter found for key: %s", argv[1]); } else { snprintf(buffer,131,"ERROR: no argument found"); } SCWrite(pCon,buffer,eError); status = 0; } return status; } /*---------------------------------------------------------------------------*/ pSICSOBJ SetupSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSOBJ pNew = NULL; int status; int type; int priv; if(argc < 3){ SCWrite(pCon,"ERROR: not enough arguments to InstallSICSOBJ",eError); return NULL; } if (argc < 5) { type = HIPNONE; priv = usInternal; } else { /* convert privilege */ priv = decodeSICSPriv(argv[3]); /* convert datatype */ strtolower(argv[4]); type = convertHdbType(argv[4]); if(type > HIPFLOAT){ SCWrite(pCon, "ERROR: invalid type requested: none, int, float supported", eError); return 0; } } pNew = MakeSICSOBJv(argv[1], argv[2], type, priv); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory creating new SICS object",eError); return NULL; } if (strcasecmp(argv[0],"DynSicsObj") == 0) { /* make object dynamic by defining a descriptor command */ SetDescriptorKey(pNew->pDes, "creationCommand", "0"); } status = AddCommand(pSics, argv[1], InterInvokeSICSOBJ, KillSICSOBJ, pNew); if(status != 1){ KillSICSOBJ(pNew); SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]); return NULL; } return pNew; } /*---------------------------------------------------------------------------*/ int InstallSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSOBJ pNew = NULL; pNew = SetupSICSOBJ(pCon, pSics, pData, argc, argv); if(pNew == NULL){ return 0; } else { return 1; } }