313 lines
9.5 KiB
C
313 lines
9.5 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"
|
|
#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;
|
|
}
|
|
RemoveHdbNodeFromParent(self->objectNode, pServ->dummyCon);
|
|
if(self->pDes != NULL){
|
|
DeleteDescriptor(self->pDes); /* kill descriptor including node */
|
|
}
|
|
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, 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.v.obj = 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);
|
|
}
|
|
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;
|
|
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],
|
|
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;
|
|
}
|
|
}
|