Files
sics/sicshdbfactory.c
Mark Koennecke f82197623e Merge branch 'master' into maverick
- Removed epicsmotor from motor.c
- Fixed a bad define in tasscanub.h
Conflicts:
	makefile_macosx
2015-03-17 14:01:40 +01:00

510 lines
14 KiB
C

/**
* 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 <sicshipadaba.h>
#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;
}