Files
sics/sicsobj.c
2007-11-27 13:36:15 +00:00

272 lines
8.2 KiB
C

/**
* This is the header file for the new (as of 2007) style SICS objects
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, July 2007
*/
#include <sics.h>
#include <tcl.h>
#include "assert.h"
#include "ifile.h"
#include "sicsobj.h"
#include "dynstring.h"
#include "macro.h"
#include "sicshipadaba.h"
extern int decodeSICSPriv(char *txt); /* from access.c */
/*--------------------------------------------------------------------------*/
static void DefaultKill(void *data){
return;
}
/*---------------------------------------------------------------------------*/
pSICSOBJ MakeSICSOBJ(char *name, char *class){
pSICSOBJ pNew = NULL;
pNew = (pSICSOBJ)malloc(sizeof(SICSOBJ));
if(pNew == NULL){
return NULL;
}
memset(pNew,0,sizeof(SICSOBJ));
pNew->pDes = CreateDescriptor(class);
pNew->objectNode = MakeHipadabaNode(name, HIPNONE, 1);
if(pNew->pDes == NULL || pNew->objectNode == NULL){
free(pNew);
return(NULL);
}
pNew->pDes->parNode = pNew->objectNode;
pNew->KillPrivate = DefaultKill;
return pNew;
}
/*---------------------------------------------------------------------------*/
void KillSICSOBJ(void *data){
pSICSOBJ self = (pSICSOBJ)data;
if(self == NULL){
return;
}
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->KillPrivate != NULL && self->pPrivate != NULL){
self->KillPrivate(self->pPrivate);
}
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.obj;
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);
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.v.obj = ScriptObjFunc;
SetHdbProperty(node,"script",argv[3]);
SetHdbProperty(node,"priv",argv[4]);
AppendHipadabaCallback(node,HCBSET,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;
}
parNode = GetHipadabaNode(self->objectNode,argv[1]);
if(parNode != NULL && parNode->value.dataType == HIPFUNC){
status = invokeOBJFunction(self, parNode, pCon, argc-2, &argv[2]);
} else {
strncpy(buffer,argv[0],130);
strcat(buffer," ");
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);
}
snprintf(buffer,131,"ERROR: no command or parameter found for key: %s",
argv[1]);
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;
if(argc < 3){
SCWrite(pCon,"ERROR: not enough arguments to InstallSICSOBJ",eError);
return NULL;
}
pNew = MakeSICSOBJ(argv[1], argv[2]);
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory creating new SICS object",eError);
return NULL;
}
status = AddCommand(pSics,
argv[1],
InvokeSICSOBJ,
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;
}
}