/** * This implements the hfactory command which is used to create * hipadaba nodes. * * copyright: see file COPYRIGHT * * Mark Koennecke, March 2008, * reusing code from former separate node creation functions. */ #include #include "statusfile.h" /*-------------------------------------------------------------------------*/ static pDynString ComposeSicsCommand(pHdb node) { char *sicsdev; pDynString sicsCommand; if (node == NULL) return NULL; sicsdev = GetHdbProp(node, "sicsdev"); if (sicsdev != NULL) { sicsCommand = CreateDynString(60,63); DynStringConcat(sicsCommand, sicsdev); return sicsCommand; } sicsCommand = ComposeSicsCommand(node->mama); if (sicsCommand) { if (strchr(GetCharArray(sicsCommand), ' ') == NULL) { DynStringConcatChar(sicsCommand, ' '); } else { DynStringConcatChar(sicsCommand, '/'); } DynStringConcat(sicsCommand, node->name); } return sicsCommand; } /*-------------------------------------------------------------------------*/ static int MakePlainNode(pHdb parent, char *name, SConnection * pCon, int argc, char *argv[]) { pHdb child = NULL; int type = 0, length = 0, priv = -1; hdbValue val; pDynString sicsCommand = NULL; if (argc < 5) { SCWrite(pCon, "ERROR: not enough arguments to create plain node", eError); return 0; } /* * convert privilege */ priv = decodeSICSPriv(argv[3]); if (priv < 0) { SCPrintf(pCon, eError, "ERROR: %s is no valid privilege code", argv[3]); return 0; } /* * convert datatype */ strtolower(argv[4]); type = convertHdbType(argv[4]); 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 < 6) { SCWrite(pCon, "ERROR: array length missing for array data type", eError); return 0; } else { length = atoi(argv[5]); } } 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); if (type != HIPNONE) { sicsCommand = ComposeSicsCommand(child); if (sicsCommand) { SetHdbProperty(child, "sicscommand", GetCharArray(sicsCommand)); DeleteDynString(sicsCommand); } } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int MakeScriptNode(pHdb parent, char *name, SConnection * pCon, int argc, char *argv[]) { int type, length = 0; pHdb child = NULL; hdbValue v; if (argc < 5) { SCWrite(pCon, "ERROR: not enough arguments to create script parameter node", eError); return 0; } /* * convert datatype */ strtolower(argv[5]); type = convertHdbType(argv[5]); 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 < 7) { SCWrite(pCon, "ERROR: array length missing for array data type", eError); return 0; } else { length = atoi(argv[6]); } } v = makeHdbValue(type, length); child = MakeSICSScriptPar(name, argv[4], argv[3], v); ReleaseHdbValue(&v); if (child == NULL) { SCWrite(pCon, "ERROR: out of memory creating node", eError); return 0; } AddHipadabaChild(parent, child, pCon); SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------------*/ static int MakeLinkNode(pHdb parent, char *name, SConnection * pCon, int argc, char *argv[]) { pHdb node = NULL; pObjectDescriptor pDes = NULL; char buffer[256]; if (argc < 4) { SCWrite(pCon, "ERROR: not enough arguments to create link node", eError); return 0; } pDes = FindCommandDescriptor(pServ->pSics, argv[3]); if (pDes == NULL) { snprintf(buffer, 255, "ERROR: failed to find object %s", argv[3]); 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[3]); SCWrite(pCon, buffer, eError); return 0; } if (pDes->parNode->mama != NULL) { snprintf(buffer, 255, "ERROR: Object %s is already linked somewhere else", argv[3]); SCWrite(pCon, buffer, eError); return 0; } AddHipadabaChild(parent, pDes->parNode, pCon); if (pDes->parNode->name != NULL) { free(pDes->parNode->name); } pDes->parNode->name = strdup(name); 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 *) mm->callData; v = *(mm->v); if (pCon == NULL) { printf("Cannot invoke command without connection\n"); return hdbAbort; } if (v.dataType == HIPTEXT) { if (strstr(v.v.text, "start") != NULL) { cmd = CreateDynString(64, 64); if (cmd == 0) { SCWrite(pCon, "ERROR: out of memory in CommandSetCallback", eError); return 0; } DynStringCopy(cmd, node->value.v.text); DynStringConcat(cmd, " "); current = node->child; while (current != NULL) { par = formatValue(current->value, current); if (par != NULL) { DynStringConcat(cmd, GetCharArray(par)); DynStringConcat(cmd, " "); DeleteDynString(par); } current = current->next; } SendHdbStatusMessage(node, "start"); status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd)); SendHdbStatusMessage(node, "stop"); DeleteDynString(cmd); if (status == 1) { return hdbContinue; } else { return hdbAbort; } } else { SCWrite(pCon, "ERROR: this node only understands start as value", eError); return hdbAbort; } } return hdbContinue; } /*---------------------------------------------------------------------------*/ static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData, pHdbMessage message) { pHdbDataMessage mm = NULL; if ((mm = GetHdbGetMessage(message)) == NULL) { return hdbContinue; } hdbValue v2 = MakeHdbText(strdup("Nothing to get")); copyHdbValue(&v2, mm->v); return hdbContinue; } /*--------------------------------------------------------------------------*/ static int MakeCommandNode(pHdb parent, char *name, SConnection * pCon, int argc, char *argv[]) { pHdb node = NULL; pHdbCallback kalle = NULL; if (argc < 4) { SCWrite(pCon, "ERROR: not enough arguments to create command node", eError); return 0; } 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[3]); node->value.arrayLength = strlen(argv[3]); SetHdbProperty(node, "sicscommand", argv[3]); SetHdbProperty(node, "scriptcommand", "yes"); 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; } /*---------------------------------------------------------------------------*/ static hdbCallbackReturn AliasSourceCallback(pHdb node, void *userData, pHdbMessage message) { SConnection *pCon = NULL; pHdb targetNode = NULL; pHdbDataMessage mm; if((mm = GetHdbSetMessage(message)) != NULL){ pCon = mm->callData; targetNode = FindHdbNode(NULL,(char *)userData, pCon); if(targetNode == NULL){ if(pCon != NULL){ SCPrintf(pCon,eError,"ERROR: link target %s not found, deleting link callbacks", (char *)userData); } return hdbKill; } SetHipadabaPar(targetNode,*mm->v,pCon); return hdbContinue; } if((mm = GetHdbGetMessage(message)) != NULL){ pCon = mm->callData; targetNode = FindHdbNode(NULL,(char *)userData, pCon); if(targetNode == NULL){ if(pCon != NULL){ SCPrintf(pCon,eError,"ERROR: link target %s not found, deleting link callbacks", (char *)userData); } return hdbKill; } GetHipadabaPar(targetNode,mm->v,pCon); copyHdbValue(mm->v,&node->value); return hdbContinue; } return hdbContinue; } /*---------------------------------------------------------------------------*/ static hdbCallbackReturn AliasTargetCallback(pHdb node, void *userData, pHdbMessage message) { SConnection *pCon = NULL; pHdb targetNode = NULL; pHdbDataMessage mm; if((mm = GetHdbUpdateMessage(message)) != NULL){ pCon = mm->callData; targetNode = FindHdbNode(NULL,(char *)userData, pCon); if(targetNode == NULL){ if(pCon != NULL){ SCPrintf(pCon,eError,"ERROR: link source %s not found, deleting link callbacks", (char *)userData); } return hdbKill; } UpdateHipadabaPar(targetNode,*mm->v,pCon); return hdbContinue; } return hdbContinue; } /*--------------------------------------------------------------------------*/ static int MakeAliasNode(pHdb parent, char *name, SConnection *pCon, int argc, char *argv[]) { hdbValue v; pHdb targetNode = NULL, child = NULL; char value[512]; const char *key; if(argc < 4){ SCWrite(pCon,"ERROR: hdbfactory alias needs 4 arguments, not enough supplied", eError); return 0; } targetNode = FindHdbNode(NULL,argv[3], pCon); if(targetNode == NULL){ SCPrintf(pCon,eError,"ERROR: alias target %s not found", argv[3]); return 0; } child = MakeHipadabaNode(name,targetNode->value.dataType, targetNode->value.arrayLength); if(child == NULL){ SCWrite(pCon,"ERROR: out of memory in hdbfactory alias", eError); return 0; } AppendHipadabaCallback(child, MakeHipadabaCallback(AliasSourceCallback, strdup(argv[3]),free)); AddHipadabaChild(parent,child, pCon); AppendHipadabaCallback(targetNode, MakeHipadabaCallback(AliasTargetCallback, strdup(argv[1]),free)); /* * copy properties */ InitHdbPropertySearch(targetNode); while((key = GetNextHdbProperty(targetNode, value, 512)) != NULL){ SetHdbProperty(child,(char *)key,value); } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ int HdbNodeFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { char *name = NULL; pHdb parent = NULL; if (!SCMatchRights(pCon, usMugger)) { return 0; } if (argc < 3) { SCWrite(pCon, "ERROR: not enough arguments to hfactory", eError); return 0; } parent = FindHdbParent(NULL, argv[1], &name, pCon); if (parent == NULL) { return 0; /* error messages written inside FindHdbParent */ } strtolower(argv[2]); if (strcmp(argv[2], "plain") == 0) { return MakePlainNode(parent, name, pCon, argc, argv); } else if (strcmp(argv[2], "script") == 0) { return MakeScriptNode(parent, name, pCon, argc, argv); } else if (strcmp(argv[2], "link") == 0) { return MakeLinkNode(parent, name, pCon, argc, argv); } else if (strcmp(argv[2], "alias") == 0) { return MakeAliasNode(parent, name, pCon, argc, argv); } else if (strcmp(argv[2], "command") == 0) { return MakeCommandNode(parent, name, pCon, argc, argv); } else { SCWrite(pCon, "ERROR: node type not recognised", eError); return 0; } return 0; }