Files
sics/scriptcontext.c
koennecke ee49c5b56a - Fixed a core dump in the sycamore protocol
- Added missing files aynnet.*
- Fixed the addition to root issue in scriptcontex
2009-02-17 08:34:46 +00:00

1127 lines
27 KiB
C

#include <strings.h>
#include <tcl.h>
#include <time.h>
#include <math.h>
#include "sics.h"
#include "sicsobj.h"
#include "splitter.h"
#include "initializer.h"
#include "commandlog.h"
#include "hipadaba.h"
#include "sicshipadaba.h"
#include "dynstring.h"
#include "devser.h"
#include "ascon.h"
#include "macro.h"
#include "scriptcontext.h"
#define MAX_HDB_PATH 1024
typedef struct ContextItem {
struct ContextItem *next;
Hdb *node;
Hdb *controllerNode;
} ContextItem;
typedef struct ScriptContext {
ObjectDescriptor *desc;
ContextItem *nodes;
ContextItem *trash;
} ScriptContext;
struct SctController {
DevSer *devser;
Hdb *node; /* the controller node */
SConnection *conn;
int verbose;
};
/* action data and write callback data */
typedef struct SctData {
char *name;
SctController *controller;
SConnection *conCtx;
int answered;
Hdb *node;
} SctData;
static ScriptContext *sct = NULL;
static SConnection *currentCon = NULL;
static struct {
char *name;
} actionCallback;
static char *mainCallback = "main callback";
void PushContext(Hdb * node, Hdb * controllerNode)
{
ContextItem *new;
if (sct->trash == NULL) {
new = calloc(1, sizeof(*new));
} else {
new = sct->trash;
sct->trash = sct->trash->next;
}
new->next = sct->nodes;
sct->nodes = new;
new->node = node;
new->controllerNode = controllerNode;
}
void PopContext(void)
{
ContextItem *c;
c = sct->nodes;
assert(c);
sct->nodes = c->next;
c->next = sct->trash;
sct->trash = c;
}
void CleanStack(Hdb * node)
{
ContextItem *s;
/* clean context from killed nodes */
for (s = sct->nodes; s != NULL; s = s->next) {
if (s->node == node) {
s->node = NULL;
}
if (s->controllerNode == node) {
s->controllerNode = NULL;
}
}
}
static void SetProp(Hdb * node, Hdb * cNode, char *key, char *value)
{
char *val;
if (node == NULL) {
if (cNode == NULL)
return;
node = cNode;
} else {
val = GetHdbProp(node, key);
if (val == NULL && cNode != NULL) {
val = GetHdbProp(cNode, key);
if (val != NULL) {
node = cNode;
}
}
}
if (value == NULL) {
if (GetHdbProperty(node, key, NULL, 0) > 0) {
SetHdbProperty(node, key, "");
}
} else {
SetHdbProperty(node, key, value);
}
}
static char *GetProp(Hdb * node, Hdb * cNode, char *key)
{
char *val;
if (node != NULL) {
val = GetHdbProp(node, key);
if (val != NULL)
return val;
}
if (cNode != NULL) {
val = GetHdbProp(cNode, key);
}
return val;
}
/*
* This is the actual sct command available in scripts.
*/
int SctCommand(SConnection * con, SicsInterp * sics, void *object,
int argc, char *argv[])
{
static char value[1024];
char *val;
char error[512];
Hdb *node = NULL;
Hdb *cNode = NULL;
hdbValue v;
double dtime;
assert(sct == object);
if (sct->nodes != NULL) {
node = sct->nodes->node;
cNode = sct->nodes->controllerNode;
}
if (node == NULL && cNode == NULL) {
SCPrintf(con, eError, "ERROR: %s may be called only in proper context",
argv[0]);
return 0;
}
if (argc <= 1) {
GetHdbPath(node, value, sizeof value);
SCWrite(con, value, eValue);
return 1;
}
/*
* update command
*/
if (strcmp(argv[1], "update") == 0) {
cloneHdbValue(&node->value, &v);
Arg2Text(argc - 2, argv + 2, value, sizeof value);
if (!readHdbValue(&v, value, error, 512)) {
SCWrite(con, error, eError);
return 0;
}
UpdateHipadabaPar(node, v, con);
SetHdbProperty(node, "geterror", NULL);
return 1;
}
/*
* print
*/
if (strcmp(argv[1], "print") == 0) {
Arg2Text(argc - 2, argv + 2, value, sizeof value);
SCWrite(con, value, eLog);
return 1;
}
/**
* controller
*/
if (strcmp(argv[1], "controller") == 0) {
SCWrite(con, cNode->name, eValue);
return 1;
}
/*
* time stamping
*/
if (strcmp(argv[1], "utime") == 0) {
if (argc < 3) {
SCWrite(con, "ERROR: need property to write time stamp too", eError);
return 0;
}
dtime = DoubleTime();
snprintf(value, 1024, "%.3f", dtime);
SetHdbProperty(node, argv[2], value);
return 1;
}
/*
* property handling
*/
if (argc == 2) { /* get case */
val = GetProp(node, cNode, argv[1]);
if (val == NULL) {
SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]);
return 0;
}
SCWrite(con, val, eValue);
} else { /* set case */
if (argc == 3) {
SetProp(node, cNode, argv[1], argv[2]);
} else {
val = Arg2Tcl(argc - 2, argv + 2, value, sizeof value);
SetProp(node, cNode, argv[1], val);
if (val != NULL && val != value)
free(val);
}
}
return 1;
}
int SctCallInContext(SConnection * con, char *script, Hdb * node,
SctController * controller, char **resPtr)
{
Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics);
int ret, l;
char *result = NULL;
int iRet = 1;
int verbose = controller->verbose;
PushContext(node, controller->node);
if (verbose) {
SCPrintf(con, eLog, "\nscript: %s\n", script);
}
MacroPush(con);
l = strlen(script);
ret = Tcl_EvalEx(pTcl, script, l, 0);
result = (char *) Tcl_GetStringResult(pTcl);
if (ret != TCL_OK && result[0] != '\0') {
if (verbose) {
SCPrintf(con, eLog, "\nerror: %s\n", result);
}
iRet = 0;
}
*resPtr = result;
MacroPop();
PopContext();
return iRet;
}
static int SctMatch(void *data1, void *data2)
{
SctData *a = data1;
SctData *b = data2;
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
}
static char *SctActionHandler(void *actionData, char *lastReply)
{
SctData *data = actionData;
Hdb *node = data->node;
SctController *controller = data->controller;
char *state;
char *result;
char *script;
char *send = NULL;
int i;
SConnection *con;
char timeKey[50], timeVal[50];
if (currentCon) {
con = currentCon;
} else {
con = controller->conn;
}
SetProp(node, controller->node, "result", lastReply);
if (controller->verbose && lastReply != NULL && *lastReply != '\0') {
SCPrintf(con, eLog, "reply : %s", lastReply);
}
state = GetProp(node, controller->node, "state");
if (state == NULL || strcasecmp(state, "idle") == 0) {
state = data->name;
SetProp(node, controller->node, "state", state);
}
for (i = 0; i < 10; i++) {
SetProp(node, controller->node, "send", NULL);
script = GetProp(node, controller->node, state);
if (script == NULL)
script = state;
if (!SctCallInContext(con, script, node, data->controller, &result)) {
SCPrintf(con, eError, "ERROR: %s", result);
goto finish;
}
state = result;
if (strcasecmp(state, "idle") == 0) {
if (currentCon && !data->answered) {
SCWrite(con, "o.k.", eValue);
}
if (strcmp(data->name, "write") == 0) {
SetHdbProperty(data->node, "writestatus", "commandsent");
}
snprintf(timeKey, 50, "%s_time", data->name);
snprintf(timeVal, 50, "%.3f", DoubleTime());
SetHdbProperty(data->node, timeKey, timeVal);
goto finish;
}
SetProp(node, controller->node, "state", state);
send = GetProp(node, controller->node, "send");
if (send != NULL && send[0] != '\0') {
if (controller->verbose) {
SCPrintf(con, eLog, "send : %s", send);
}
return send;
}
}
SCPrintf(con, eLogError, "ERROR: too many quick scripts chained");
finish:
SetProp(node, controller->node, "state", "idle");
if (data->conCtx != NULL) {
SCDeleteConnection(data->conCtx);
data->conCtx = NULL;
}
return send;
}
static char *SctWriteHandler(void *actionData, char *lastReply)
{
SctData *data = actionData;
SConnection *old;
char *result;
old = currentCon;
currentCon = data->conCtx;
result = SctActionHandler(data, lastReply);
currentCon = old;
return result;
}
static int SctMatchNode(void *vNode, void *vData)
{
Hdb *node = vNode;
SctData *d = vData;
return node == d->node;
}
static hdbCallbackReturn SctMainCallback(Hdb * node, void *userData,
hdbMessage * msg)
{
SctController *controller = userData;
hdbDataSearch *dsm;
hdbDataMessage *mm;
hdbPtrMessage *pm;
hdbMessage *km;
ContextItem *s;
SConnection *con;
char *geterror;
char error[256];
pm = GetKillPtrMessage(msg);
if (pm != NULL) {
if (controller == pm->pPtr) {
return hdbKill;
}
return hdbContinue;
}
dsm = GetHdbDataSearchMessage(msg);
if (dsm != NULL) {
if (dsm->testPtr == controller) {
dsm->result = controller;
return hdbAbort;
}
return hdbContinue;
}
km = GetHdbKillNodeMessage(msg);
if (km != NULL) {
/* unschedule all actions related to this node */
DevUnschedule(controller->devser, node, SctActionHandler,
SctMatchNode);
CleanStack(node);
return hdbContinue;
}
mm = GetHdbGetMessage(msg);
if (mm != NULL) {
con = mm->callData;
geterror = GetHdbProp(node, "geterror");
if (geterror != NULL) {
snprintf(error,255,"ERROR: %s", geterror);
SCWrite(con, error, eError);
if(mm->v->dataType == HIPTEXT){
if(mm->v->v.text != NULL){
free(mm->v->v.text);
}
mm->v->v.text = strdup(error);
}
return hdbAbort;
}
return hdbContinue;
}
return hdbContinue;
}
static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
hdbMessage * msg)
{
hdbDataSearch *dsm;
hdbDataMessage *mm;
hdbPtrMessage *pm;
hdbMessage *km;
SctData *data = userData;
Hdb *target;
char *script;
int l;
int iRet;
pDynString text;
DevPrio prio;
char *writeprio;
char *error;
SConnection *con;
SConnection *con2;
char path[MAX_HDB_PATH];
pm = GetKillPtrMessage(msg);
if (pm != NULL) {
if (data->controller == pm->pPtr) {
return hdbKill;
}
return hdbContinue;
}
dsm = GetHdbDataSearchMessage(msg);
if (dsm != NULL) {
if (dsm->testPtr == &actionCallback) {
if (strcasecmp(data->name, actionCallback.name) == 0) {
dsm->result = data;
}
return hdbAbort;
}
return hdbContinue;
}
mm = GetHdbSetMessage(msg);
if (mm != NULL) {
con = mm->callData;
/* set target value */
text = formatValue(*(mm->v), node);
SetHdbProperty(node, "target", GetCharArray(text));
/* call check script, if available */
script = GetProp(node, data->controller->node, "check");
if (script != NULL) {
if (SctCallInContext(con, script, node, data->controller, &error) ==
0) {
SCPrintf(con, eError, "ERROR: %s", error);
SetHdbProperty(node, "target", NULL);
return hdbAbort;
}
}
/* enqueue write action */
writeprio = GetProp(node, data->controller->node, "writeprio");
if (writeprio != NULL) {
prio = DevText2Prio(writeprio);
if (prio == NullPRIO) {
SCPrintf(con, eError, "ERROR: unknown priority: %s", writeprio);
prio = WritePRIO;
}
} else {
prio = WritePRIO;
}
if (data->conCtx != NULL) {
GetHdbPath(node, path, sizeof path);
SCPrintf(data->conCtx, eLog,
"%s target changed to %s before completion", path,
GetCharArray(text));
}
DeleteDynString(text);
data->conCtx = SCCopyConnection(con);
data->answered = 0;
DevQueue(data->controller->devser, data, prio,
SctWriteHandler, SctMatch, NULL);
/* no kill function in DevQueue: data is owned by the node (callback list) */
return hdbContinue;
}
mm = GetHdbUpdateMessage(msg);
if (mm != NULL) {
if (currentCon) { /* update called from a write action */
data->answered = 1;
GetHdbPath(node, path, sizeof path);
con = currentCon;
text = formatValue(*(mm->v), node);
/* Markus: who is receiving this message?
It gave unwanted output to me. MK
SCPrintf(con, eLog, "%s = %s", path, GetCharArray(text));
*/
DeleteDynString(text);
}
return hdbContinue;
}
return hdbContinue;
}
static char *ParText(Hdb * cmdNode, char *name,
int nPar, char *defaultValue)
{
Hdb *par;
for (par = cmdNode->child; nPar > 0 && par != NULL;
par = par->next, nPar--) {
if (strcasecmp(par->name, name) == 0) {
if (par->value.dataType == HIPTEXT) {
return par->value.v.text;
}
}
}
return defaultValue;
}
static double ParValue(Hdb * cmdNode, char *name,
int nPar, double defaultValue)
{
Hdb *par;
for (par = cmdNode->child; nPar > 0 && par != NULL;
par = par->next, nPar--) {
if (strcasecmp(par->name, name) == 0) {
switch (par->value.dataType) {
case HIPINT:
return par->value.v.intValue;
case HIPFLOAT:
return par->value.v.doubleValue;
}
}
}
return defaultValue;
}
static void SctKillData(void *d)
{
SctData *data = d;
if (data->name)
free(data->name);
if (data->conCtx)
SCDeleteConnection(data->conCtx);
free(data);
}
static void SctKillCBData(void *d)
{
SctData *data = d;
DevRemoveAction(data->controller->devser, data);
SctKillData(d);
}
int SctAddPollNode(SctController * controller, Hdb * node, double interval,
DevPrio prio, char *action)
{
SctData *data;
hdbCallback *cb;
if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(cb);
AppendHipadabaCallback(node, cb);
SetHdbProperty(node, "geterror", "Not read yet");
}
data = calloc(1, sizeof(*data));
assert(data);
data->controller = controller;
data->node = node;
data->conCtx = NULL; /* we might need a dummy connection here */
data->name = strdup(action);
return DevSchedule(controller->devser, data, prio, interval,
SctActionHandler, SctMatch, SctKillData);
}
static int SctPollCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
Hdb *node;
SctController *controller;
double interval;
char *path;
DevPrio prio;
char *action;
char *prioText;
if (nPar < 1) {
SCPrintf(con, eError,
"ERROR: should be: %s poll <node> (<interval> <prio> <action>)",
ccmd->objectNode->name);
return 0;
}
controller = ccmd->pPrivate;
path = ParText(cmdNode, "node", nPar, "");
node = FindHdbNode(NULL, path, con);
if (node == NULL) {
SCPrintf(con, eError, "ERROR: %s not found", path);
return 0;
}
interval = ParValue(cmdNode, "interval", nPar, 5);
prioText = ParText(cmdNode, "prio", nPar, "read");
prio = DevText2Prio(prioText);
if (prio == NullPRIO) {
SCPrintf(con, eError, "ERROR: unknown priority: %s", prioText);
return 0;
}
action = ParText(cmdNode, "action", nPar, "read");
if (SctAddPollNode(controller, node, interval, prio, action) > 0) {
SCPrintf(con, eValue,
"%s poll on %s changed to %g sec, %s prio",
action, path, interval, prioText);
} else {
SCPrintf(con, eValue,
"%s poll registered on %s (%g sec, %s prio)",
action, path, interval, prioText);
}
return 1;
}
static int SctUnpollCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
SctController *controller;
double interval;
char *path;
DevPrio prio;
char *prioText;
SctData data;
if (nPar < 1) {
SCPrintf(con, eError,
"ERROR: should be: %s poll <node> (<action>)",
ccmd->objectNode->name);
return 0;
}
controller = ccmd->pPrivate;
path = ParText(cmdNode, "node", nPar, "");
data.node = FindHdbNode(NULL, path, con);
if (data.node == NULL) {
SCPrintf(con, eError, "ERROR: %s not found", path);
return 0;
}
data.name = ParText(cmdNode, "action", nPar, "read");
if (DevUnschedule(controller->devser, &data, SctActionHandler, SctMatch)
== 0) {
SCPrintf(con, eValue, "%s poll not found on %s", data.name, path);
} else {
SCSendOK(con);
}
return 1;
}
static int SctConnectCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
Hdb *node;
SctController *controller;
char *path;
hdbCallback *cb;
if (nPar < 1) {
SCPrintf(con, eError,
"ERROR: should be: %s connect <node> ",
ccmd->objectNode->name);
return 0;
}
controller = ccmd->pPrivate;
path = ParText(cmdNode, "node", nPar, "");
node = FindHdbNode(NULL, path, con);
if (node == NULL) {
SCPrintf(con, eError, "ERROR: %s not found", path);
return 0;
}
if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(cb);
AppendHipadabaCallback(node, cb);
}
SCSendOK(con);
return 1;
}
int SctAddWriteNode(SctController * controller, Hdb * node)
{
hdbCallback *cb;
SctData *data;
if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(cb);
AppendHipadabaCallback(node, cb);
}
actionCallback.name = "write"; /* local, so no strdup here */
data = FindHdbCallbackData(node, &actionCallback);
if (data != NULL) {
return 0;
}
data = calloc(1, sizeof(*data));
assert(data);
data->controller = controller;
data->node = node;
data->conCtx = NULL;
data->name = strdup("write");
cb = MakeHipadabaCallback(SctActionCallback, data, SctKillCBData);
assert(cb);
data->node = node;
AppendHipadabaCallback(node, cb);
RemoveSetUpdateCallback(node);
return 1;
}
static int SctWriteCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
Hdb *node;
SctController *controller;
double interval;
char *path;
if (nPar < 1) {
SCPrintf(con, eError, "ERROR: should be: %s write <node>",
ccmd->objectNode->name);
return 0;
}
controller = ccmd->pPrivate;
path = ParText(cmdNode, "node", nPar, "");
node = FindHdbNode(NULL, path, con);
if (node == NULL) {
SCPrintf(con, eError, "ERROR: %s not found", path);
return 0;
}
if (SctAddWriteNode(controller, node) == 0) {
SCPrintf(con, eError, "ERROR: %s has already a write action", path);
return 0;
}
SCSendOK(con);
return 1;
}
void SctQueueNode(SctController * controller, Hdb * node,
DevPrio prio, char *action, SConnection * con)
{
SctData *data;
hdbCallback *cb;
if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(cb);
AppendHipadabaCallback(node, cb);
}
data = calloc(1, sizeof(*data));
assert(data);
data->controller = controller;
data->node = node;
data->name = strdup(action);
data->conCtx = NULL;
if (!DevQueue(data->controller->devser, data, prio,
SctWriteHandler, SctMatch, SctKillData)) {
if (data->name != NULL) {
free(data->name);
}
free(data);
} else {
if (con != NULL) {
data->conCtx = SCCopyConnection(con);
}
}
return;
}
static int SctQueueCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
Hdb *node;
SctController *controller;
double interval;
char *path;
char *action;
DevPrio prio;
SctData *data;
char *prioText;
if (nPar < 2) {
SCPrintf(con, eError,
"ERROR: should be: %s queue <node> <prio> <action>",
ccmd->objectNode->name);
return 0;
}
controller = ccmd->pPrivate;
path = ParText(cmdNode, "node", nPar, "");
node = FindHdbNode(NULL, path, con);
if (node == NULL) {
SCPrintf(con, eError, "ERROR: %s not found", path);
return 0;
}
prioText = ParText(cmdNode, "prio", nPar, "write");
prio = DevText2Prio(prioText);
if (prio == NullPRIO) {
SCPrintf(con, eError, "ERROR: unknown priority: %s", prioText);
return 0;
}
action = ParText(cmdNode, "action", nPar, "write");
SctQueueNode(controller, node, prio, action, con);
return 1;
}
typedef struct SctTransact {
char *command;
int sent;
SConnection *con;
} SctTransact, *pSctTransact;
static void KillSctTransact(void *data)
{
pSctTransact self = (pSctTransact) data;
if (self == NULL) {
return;
}
if (self->command) {
free(self->command);
}
if (self->con) {
SCDeleteConnection(self->con);
}
free(self);
}
static char *TransactionHandler(void *actionData, char *lastReply)
{
pSctTransact st = (pSctTransact) actionData;
if (st->sent == 0) {
st->sent = 1;
return st->command;
} else {
st->sent = 2;
SCWrite(st->con, lastReply, eValue);
return NULL;
}
}
static int SctTransactMatch(void *d1, void *d2)
{
return d1 == d2;
}
static int SctTransactCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pSctTransact st = NULL;
SctController *c;
c = (SctController *) ccmd->pPrivate;
st = calloc(sizeof(SctTransact), 1);
if (st == NULL) {
SCWrite(con, "ERROR: out of memory in SctTransactCommand", eError);
return 0;
}
st->con = SCCopyConnection(con);
st->command = strdup(par[0]->value.v.text);
DevQueue(c->devser, st, WritePRIO,
TransactionHandler, SctTransactMatch, NULL);
while (st->sent != 2) {
TaskYield(pServ->pTasker);
if (SCGetInterrupt(con) != eContinue) {
break;
}
}
KillSctTransact(st);
return 1;
}
static int SctSendCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pSctTransact st = NULL;
SctController *c;
char *prioText = NULL;
int prio;
c = (SctController *) ccmd->pPrivate;
st = calloc(sizeof(SctTransact), 1);
if (st == NULL) {
SCWrite(con, "ERROR: out of memory in SctSendCmd", eError);
return 0;
}
st->con = SCCopyConnection(con);
st->command = strdup(par[0]->value.v.text);
prioText = ParText(cmdNode, "prio", nPar, "write");
prio = DevText2Prio(prioText);
if (prio == NullPRIO) {
prio = WritePRIO;
}
DevQueue(c->devser, st, prio,
TransactionHandler, SctTransactMatch, KillSctTransact);
return 1;
}
static int SctDisconnect(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
SctController *c;
c = (SctController *) ccmd->pPrivate;
DevDisconnect(c->devser);
return 1;
}
static hdbCallbackReturn SctDebugCallback(Hdb * node, void *userData,
hdbMessage * msg)
{
hdbDataMessage *mm;
SctController *controller = userData;
SConnection *con;
int i;
mm = GetHdbSetMessage(msg);
if (mm != NULL) {
i = mm->v->v.intValue;
if (i < 0) {
controller->verbose = 0;
DevDebugMode(controller->devser, -1);
} else if (i == 0) {
controller->verbose = 1;
DevDebugMode(controller->devser, -1);
} else {
controller->verbose = 1;
DevDebugMode(controller->devser, i);
}
}
return hdbContinue;
}
static void SctKillController(void *c)
{
SctController *controller = c;
SConnection *con;
CleanStack(controller->node);
RemoveSICSInternalCallback(controller);
if (controller->conn) {
SCDeleteConnection(controller->conn);
}
DevKill(controller->devser);
free(controller);
}
static int SctMakeController(SConnection * con, SicsInterp * sics,
void *object, int argc, char *argv[])
{
SICSOBJ *ccmd;
Hdb *parent, *par, *cmd;
char *nodeName;
hdbCallback *cb;
SctController *controller;
if (argc < 2) {
SCPrintf(con, eError,
"ERROR: should be %s <path> <protocol args> ...", argv[0]);
return 0;
}
/*
* Install into the Hipadaba when full path given
*/
if(strstr(argv[1],"/") != NULL){
parent = FindHdbParent(NULL, argv[1], &nodeName, con);
if (parent == NULL)
return 0; /* error message already written */
} else {
nodeName = argv[1];
parent = NULL;
}
controller = calloc(1, sizeof(*controller));
assert(controller);
controller->verbose = 0;
ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy);
controller->node = ccmd->objectNode;
controller->conn = SCCreateDummyConnection(pServ->pSics);
assert(ccmd);
assert(controller->node->mama == NULL);
ccmd->pPrivate = controller;
ccmd->KillPrivate = SctKillController;
if(parent != NULL){
AddHipadabaChild(parent, controller->node, con);
}
controller->devser = DevMake(con, argc - 2, argv + 2);
if (!controller->devser)
return 0;
AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd);
SetDescriptorKey(ccmd->pDes, "creationCommand", "0");
cmd = AddSICSHdbPar(controller->node,
"poll", usMugger, MakeSICSFunc(SctPollCmd));
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0));
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read"));
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read"));
cmd = AddSICSHdbPar(controller->node,
"unpoll", usMugger, MakeSICSFunc(SctUnpollCmd));
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read"));
cmd = AddSICSHdbPar(controller->node,
"connect", usMugger, MakeSICSFunc(SctConnectCmd));
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
cmd = AddSICSHdbPar(controller->node,
"write", usMugger, MakeSICSFunc(SctWriteCmd));
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
cmd = AddSICSHdbPar(controller->node,
"queue", usMugger, MakeSICSFunc(SctQueueCmd));
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write"));
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write"));
cmd = AddSICSHdbPar(controller->node,
"transact", usMugger, MakeSICSFunc(SctTransactCmd));
AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText(""));
cmd = AddSICSHdbPar(controller->node,
"send", usMugger, MakeSICSFunc(SctSendCmd));
AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText(""));
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText(""));
cmd = AddSICSHdbPar(controller->node,
"disconnect", usMugger, MakeSICSFunc(SctDisconnect));
par = AddSICSHdbPar(controller->node, "debug", usUser, MakeHdbInt(-1));
cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL);
if (cb)
AppendHipadabaCallback(par, cb);
return 1;
}
void SctKill(void *object)
{
assert(sct == object);
ContextItem *p, *q;
for (p = sct->nodes; p != NULL; p = q) {
q = p->next;
free(p);
}
for (p = sct->trash; p != NULL; p = q) {
q = p->next;
free(p);
}
if (sct->desc != NULL) {
DeleteDescriptor(sct->desc);
}
free(sct);
sct = NULL;
}
void SctInit(void)
{
if (sct)
return;
sct = calloc(1, sizeof(*sct));
assert(sct);
sct->desc = CreateDescriptor("ScriptContext");
AddCommand(pServ->pSics, "sct", SctCommand, SctKill, sct);
AddCmd("makesctcontroller", SctMakeController);
}
int SctVerbose(SctController * c)
{
return c->verbose;
}