/** * 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" #define MAX_HDB_PATH 1024 /*-------------------------------------------------------------------------*/ 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; 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); SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int MakeScriptNode(pHdb parent, char *name, SConnection *pCon, int argc, char *argv[]){ int type, length; 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 script 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 *)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 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]); 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; } /*--------------------------------------------------------------------------*/ 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],"command") == 0){ return MakeCommandNode(parent,name,pCon,argc,argv); } else { SCWrite(pCon,"ERROR: node type not recognised", eError); return 0; } return 0; }