- design improvements in scriptcontext (sct send) and ascon (AsconBaseHandler)
- bug fixes
This commit is contained in:
207
ascon.c
207
ascon.c
@ -15,6 +15,7 @@
|
|||||||
#include "uselect.h"
|
#include "uselect.h"
|
||||||
|
|
||||||
static double lastClose = 0; /* time of last close operation */
|
static double lastClose = 0; /* time of last close operation */
|
||||||
|
static AsconProtocol *protocols = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
|
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
|
||||||
@ -132,6 +133,10 @@ static void AsconConnect(Ascon * a)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (a->hostport == NULL) {
|
||||||
|
AsconError(a, "no host:port given", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
colon = strchr(a->hostport, ':');
|
colon = strchr(a->hostport, ':');
|
||||||
if (colon == NULL)
|
if (colon == NULL)
|
||||||
return;
|
return;
|
||||||
@ -167,28 +172,6 @@ static void AsconConnect(Ascon * a)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
|
||||||
{
|
|
||||||
a->fd = -1;
|
|
||||||
a->state = AsconConnectStart;
|
|
||||||
a->hostport = strdup(argv[1]);
|
|
||||||
if (argc > 2) {
|
|
||||||
a->sendTerminator = strdup(argv[2]);
|
|
||||||
} else {
|
|
||||||
a->sendTerminator = strdup("\n");
|
|
||||||
}
|
|
||||||
if (argc > 3) {
|
|
||||||
a->timeout = atof(argv[3]);
|
|
||||||
} else {
|
|
||||||
a->timeout = 2.0; /* sec */
|
|
||||||
}
|
|
||||||
a->replyTerminator == NULL;
|
|
||||||
if (argc > 4 && argv[4][0] != '\0') {
|
|
||||||
a->replyTerminator = strdup(argv[4]);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AsconReadGarbage(int fd)
|
int AsconReadGarbage(int fd)
|
||||||
{
|
{
|
||||||
fd_set rmask;
|
fd_set rmask;
|
||||||
@ -315,14 +298,14 @@ int AsconWriteChars(int fd, char *data, int length)
|
|||||||
|
|
||||||
static double lastCall = 0;
|
static double lastCall = 0;
|
||||||
|
|
||||||
int AsconStdHandler(Ascon * a)
|
int AsconBaseHandler(Ascon * a)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int l;
|
int l;
|
||||||
char chr;
|
char chr;
|
||||||
double now = DoubleTime();
|
double now = DoubleTime();
|
||||||
|
|
||||||
if (now > lastCall + 0.5) { /* AsconStdHandler was not called since a long time (0.5 sec) */
|
if (now > lastCall + 0.5) { /* AsconBaseHandler was not called since a long time (0.5 sec) */
|
||||||
if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
|
if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
|
||||||
a->start += now - lastCall - 0.5;
|
a->start += now - lastCall - 0.5;
|
||||||
}
|
}
|
||||||
@ -343,26 +326,13 @@ int AsconStdHandler(Ascon * a)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AsconWriteStart:
|
case AsconWriteStart:
|
||||||
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
|
if (a->sendTerminator) {
|
||||||
a->state = AsconWriteDone;
|
|
||||||
} else {
|
|
||||||
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
||||||
a->wrPos = 0;
|
|
||||||
a->state = AsconWriting;
|
|
||||||
}
|
}
|
||||||
|
a->wrPos = 0;
|
||||||
|
a->state = AsconWriting;
|
||||||
break;
|
break;
|
||||||
case AsconWriting:
|
case AsconWriting:
|
||||||
if (a->readState) { /* last char was CR */
|
|
||||||
ret = AsconReadChar(a->fd, &chr);
|
|
||||||
if (ret > 0) {
|
|
||||||
if (chr == '\n') {
|
|
||||||
/* swallow LF after CR */
|
|
||||||
a->readState = 0;
|
|
||||||
} else {
|
|
||||||
/* garbage character found */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AsconReadGarbage(a->fd);
|
AsconReadGarbage(a->fd);
|
||||||
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||||
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||||
@ -382,56 +352,24 @@ int AsconStdHandler(Ascon * a)
|
|||||||
break;
|
break;
|
||||||
case AsconReading:
|
case AsconReading:
|
||||||
ret = AsconReadChar(a->fd, &chr);
|
ret = AsconReadChar(a->fd, &chr);
|
||||||
if (ret > 0) {
|
if (ret <= 0) {
|
||||||
a->start = DoubleTime();
|
if (ret < 0) {
|
||||||
|
AsconError(a, "ASC5", errno);
|
||||||
if (a->replyTerminator != NULL) {
|
return 0;
|
||||||
if (strchr(a->replyTerminator, chr) != NULL) {
|
}
|
||||||
DynStringConcatChar(a->rdBuffer, chr);
|
if (a->timeout > 0) {
|
||||||
DynStringConcatChar(a->rdBuffer, '\0');
|
if (DoubleTime() - a->start > a->timeout) {
|
||||||
a->state = AsconReadDone;
|
AsconError(a, "no response", 0);
|
||||||
break;
|
a->state = AsconTimeout;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chr == '\n') {
|
|
||||||
if (a->readState) { /* last char was CR */
|
|
||||||
/* swallow LF after CR */
|
|
||||||
a->readState = 0;
|
|
||||||
chr = 0;
|
|
||||||
} else {
|
|
||||||
DynStringConcatChar(a->rdBuffer, '\0');
|
|
||||||
a->state = AsconReadDone;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (chr == '\r') {
|
|
||||||
a->readState = 1; /* set 'last char was CR' */
|
|
||||||
DynStringConcatChar(a->rdBuffer, '\0');
|
|
||||||
a->state = AsconReadDone;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chr != 0) {
|
return 0;
|
||||||
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
|
||||||
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
a->readState = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
a->lastChar = chr;
|
||||||
AsconError(a, "ASC5", errno);
|
a->start = DoubleTime();
|
||||||
return 1;
|
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
|
||||||
}
|
AsconError(a, "ASC6", errno);
|
||||||
if (a->state == AsconReadDone) {
|
return 0;
|
||||||
DynStringConcatChar(a->rdBuffer, '\0');
|
|
||||||
} else if (ret > 0) {
|
|
||||||
return 0; /* characater read: recycle */
|
|
||||||
}
|
|
||||||
if (a->timeout > 0) {
|
|
||||||
if (DoubleTime() - a->start > a->timeout) {
|
|
||||||
AsconError(a, "no response", 0);
|
|
||||||
a->state = AsconTimeout;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -440,8 +378,6 @@ int AsconStdHandler(Ascon * a)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AsconProtocol *protocols = NULL;
|
|
||||||
|
|
||||||
void AsconInsertProtocol(AsconProtocol *protocol) {
|
void AsconInsertProtocol(AsconProtocol *protocol) {
|
||||||
protocol->next = protocols;
|
protocol->next = protocols;
|
||||||
protocols = protocol;
|
protocols = protocol;
|
||||||
@ -472,6 +408,88 @@ AsconHandler AsconSetHandler(Ascon *a, SConnection *con,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- standard handler ---- */
|
||||||
|
|
||||||
|
int AsconStdHandler(Ascon * a)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char chr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (a->state) {
|
||||||
|
case AsconWriteStart:
|
||||||
|
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break; /* go to the base handler */
|
||||||
|
case AsconWriting:
|
||||||
|
if (a->readState) { /* last char was CR */
|
||||||
|
ret = AsconReadChar(a->fd, &chr);
|
||||||
|
if (ret > 0) {
|
||||||
|
if (chr == '\n') {
|
||||||
|
/* swallow LF after CR */
|
||||||
|
a->readState = 0;
|
||||||
|
} else {
|
||||||
|
/* garbage character found -> swallow */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; /* go to the base handler */
|
||||||
|
case AsconReading:
|
||||||
|
result = AsconBaseHandler(a);
|
||||||
|
if (result == 0)
|
||||||
|
return 0;
|
||||||
|
chr = a->lastChar;
|
||||||
|
if (a->replyTerminator != NULL) {
|
||||||
|
if (strchr(a->replyTerminator, chr) != NULL) {
|
||||||
|
DynStringConcatChar(a->rdBuffer, '\0');
|
||||||
|
a->state = AsconReadDone;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chr == '\n') {
|
||||||
|
if (a->readState) { /* last char was CR */
|
||||||
|
/* swallow LF after CR */
|
||||||
|
a->readState = 0;
|
||||||
|
} else {
|
||||||
|
DynStringBackspace(a->rdBuffer); /* remove LF */
|
||||||
|
DynStringConcatChar(a->rdBuffer, '\0');
|
||||||
|
a->state = AsconReadDone;
|
||||||
|
}
|
||||||
|
} else if (chr == '\r') {
|
||||||
|
a->readState = 1; /* set 'last char was CR' */
|
||||||
|
DynStringBackspace(a->rdBuffer); /* remove CR */
|
||||||
|
DynStringConcatChar(a->rdBuffer, '\0');
|
||||||
|
a->state = AsconReadDone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1; /* base handler was already called */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return AsconBaseHandler(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
a->hostport = strdup(argv[1]);
|
||||||
|
if (argc > 2) {
|
||||||
|
a->sendTerminator = strdup(argv[2]);
|
||||||
|
} else {
|
||||||
|
a->sendTerminator = strdup("\n");
|
||||||
|
}
|
||||||
|
if (argc > 3) {
|
||||||
|
a->timeout = atof(argv[3]);
|
||||||
|
} else {
|
||||||
|
a->timeout = 2.0; /* sec */
|
||||||
|
}
|
||||||
|
a->replyTerminator = NULL;
|
||||||
|
if (argc > 4 && argv[4][0] != '\0') {
|
||||||
|
a->replyTerminator = strdup(argv[4]);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* --- implementation of higher level interface ---- */
|
/* --- implementation of higher level interface ---- */
|
||||||
|
|
||||||
char *ConcatArgs(int argc, char *argv[])
|
char *ConcatArgs(int argc, char *argv[])
|
||||||
@ -489,6 +507,15 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
|
|||||||
SCWrite(con, "ERROR: no memory", eError);
|
SCWrite(con, "ERROR: no memory", eError);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
a->fd = -1;
|
||||||
|
a->state = AsconConnectStart;
|
||||||
|
a->timeout = 2.0; /* 2 sec default */
|
||||||
|
a->reconnectInterval = 10; /* 10 sec default */
|
||||||
|
a->replyTerminator = NULL;
|
||||||
|
a->sendTerminator = NULL;
|
||||||
|
a->hostport = NULL;
|
||||||
|
a->responseValid = 0;
|
||||||
|
|
||||||
a->handler = AsconSetHandler(a, con, argc, argv);
|
a->handler = AsconSetHandler(a, con, argc, argv);
|
||||||
if (a->handler == NULL) {
|
if (a->handler == NULL) {
|
||||||
args = ConcatArgs(argc, argv);
|
args = ConcatArgs(argc, argv);
|
||||||
@ -501,7 +528,7 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
|
|||||||
a->rdBuffer = CreateDynString(60, 63);
|
a->rdBuffer = CreateDynString(60, 63);
|
||||||
a->wrBuffer = CreateDynString(60, 63);
|
a->wrBuffer = CreateDynString(60, 63);
|
||||||
a->errmsg = CreateDynString(60, 63);
|
a->errmsg = CreateDynString(60, 63);
|
||||||
a->responseValid = 0;
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
ascon.i
65
ascon.i
@ -51,25 +51,26 @@ typedef int (* AsconHandler)(Ascon *connection);
|
|||||||
* all members are public, allowing access by handler wrappers
|
* all members are public, allowing access by handler wrappers
|
||||||
*/
|
*/
|
||||||
struct Ascon {
|
struct Ascon {
|
||||||
AsconState state; /**< the current state */
|
AsconState state; /**< the current state */
|
||||||
int fd; /**< socket */
|
int fd; /**< socket */
|
||||||
int readState; /**< default implementation: 'was cr' */
|
int readState; /**< default implementation: 'was cr' */
|
||||||
pDynString rdBuffer;/**< read buffer */
|
pDynString rdBuffer; /**< read buffer */
|
||||||
pDynString wrBuffer;/**< write buffer */
|
pDynString wrBuffer; /**< write buffer */
|
||||||
int wrPos; /**< write buffer position */
|
int wrPos; /**< write buffer position */
|
||||||
double timeout; /**< read timeout (sec) */
|
double timeout; /**< read timeout (sec) */
|
||||||
char *sendTerminator; /**< terminator for sending messages */
|
char *sendTerminator; /**< terminator for sending messages */
|
||||||
char *replyTerminator; /**< terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
char *replyTerminator; /**< terminator list for reply. NULL is the special case CR, LF or CR/LF */
|
||||||
char *hostport; /**< host:port to connect */
|
char *hostport; /**< host:port to connect */
|
||||||
pDynString errmsg; /**< error message */
|
pDynString errmsg; /**< error message */
|
||||||
double start; /**< unix time when read was started */
|
double start; /**< unix time when read was started */
|
||||||
void *private; /**< private data of protocol */
|
void *private; /**< private data of protocol */
|
||||||
void (*killPrivate)(void *); /** < kill function for private */
|
void (*killPrivate)(void *); /** < kill function for private */
|
||||||
int noResponse; /**< no response expected */
|
int noResponse; /**< no response expected */
|
||||||
int responseValid; /**< a valid response is ready */
|
int responseValid; /**< a valid response is ready */
|
||||||
AsconHandler handler; /**< handler function */
|
AsconHandler handler; /**< handler function */
|
||||||
double reconnectInterval; /**< reconnect interval */
|
double reconnectInterval; /**< reconnect interval */
|
||||||
double lastReconnect; /**< last reconnect try */
|
double lastReconnect; /**< last reconnect try */
|
||||||
|
char lastChar; /**< last char read */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASCON_SELECT_ERROR -1
|
#define ASCON_SELECT_ERROR -1
|
||||||
@ -77,14 +78,25 @@ struct Ascon {
|
|||||||
#define ASCON_SEND_ERROR -3
|
#define ASCON_SEND_ERROR -3
|
||||||
#define ASCON_DISCONNECTED -4
|
#define ASCON_DISCONNECTED -4
|
||||||
|
|
||||||
|
/** \brief the basic handler routine.
|
||||||
|
* \param a the connection
|
||||||
|
* \return when the state before the call was not AsconReading, the return
|
||||||
|
* value should be 1
|
||||||
|
* when the state was AsconReading, a 1 indicates that a character was read
|
||||||
|
* and the character is stored in the lastChar field. A 0 indicates
|
||||||
|
* that no charater was read.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* In most cases a custom handler may be a wrapper around AsconBaseHandler
|
||||||
|
* or around AsconStdHandler
|
||||||
|
*/
|
||||||
|
int AsconBaseHandler(Ascon *a);
|
||||||
|
|
||||||
/** \brief the standard handler routine.
|
/** \brief the standard handler routine.
|
||||||
* \param a the connection
|
* \param a the connection
|
||||||
* \return 0 when it makes sense to call the handler again immediately
|
* \return see AsconBaseHandler
|
||||||
* (for example while reading, after a character was read, as
|
|
||||||
* there may be more chars in the buffer)
|
|
||||||
* 1 else
|
|
||||||
*
|
*
|
||||||
* In most cases a custom handler may be a wrapper around AsconStdHandler
|
* features: see description of AsconStdInit
|
||||||
*/
|
*/
|
||||||
int AsconStdHandler(Ascon *a);
|
int AsconStdHandler(Ascon *a);
|
||||||
|
|
||||||
@ -94,12 +106,13 @@ int AsconStdHandler(Ascon *a);
|
|||||||
* \param argc number of arguments
|
* \param argc number of arguments
|
||||||
* \param argv arguments ("<host>:<port>" [sendTerminator] [timeout] [replyTerminators])
|
* \param argv arguments ("<host>:<port>" [sendTerminator] [timeout] [replyTerminators])
|
||||||
* sendTerminator is a character or string sent at the end of a command
|
* sendTerminator is a character or string sent at the end of a command
|
||||||
* timoeut is in seconds
|
* timeout is in seconds
|
||||||
* replyTerminator is a string, meant as a list of terminator characters
|
* replyTerminator is a string, meant as a list of terminator characters
|
||||||
* if not replyTerminator is given, CR, LF or CR/LF all are detected as
|
* if not replyTerminator is given, CR, LF or CR/LF all are detected as
|
||||||
* terminators
|
* terminators. In this case the terminator is removed from the result,
|
||||||
|
* where in the case before, the terminator stays in the result.
|
||||||
*
|
*
|
||||||
* In most cases a custom init function may be a wrapper around AsconStdInit
|
* In many cases a custom init function may be a wrapper around AsconStdInit
|
||||||
*/
|
*/
|
||||||
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[]);
|
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[]);
|
||||||
|
|
||||||
|
10
exebuf.c
10
exebuf.c
@ -233,15 +233,13 @@ int exeBufProcess(pExeBuf self, SicsInterp * pSics,
|
|||||||
SCPrintf(pCon, eLogError, "ERROR: Tcl reported: %s",
|
SCPrintf(pCon, eLogError, "ERROR: Tcl reported: %s",
|
||||||
pTcl->result);
|
pTcl->result);
|
||||||
}
|
}
|
||||||
SCWrite(pCon, "ERROR: Tcl error in block:", eLogError);
|
|
||||||
SCWrite(pCon, GetCharArray(command), eError);
|
|
||||||
SCWrite(pCon, "ERROR: end of Tcl error block", eLogError);
|
|
||||||
} else {
|
} else {
|
||||||
if(strstr(pTcl->result, "ERROR") != NULL){
|
SCWrite(pCon, pTcl->result, eError);
|
||||||
SCPrintf(pCon,eError,"%s occurred in %s", pTcl->result, cmd );
|
|
||||||
}
|
|
||||||
pCon->sicsError = 0;
|
pCon->sicsError = 0;
|
||||||
}
|
}
|
||||||
|
SCWrite(pCon, "ERROR: above error was in block:", eError);
|
||||||
|
SCWrite(pCon, cmd, eError);
|
||||||
|
SCWrite(pCon, "ERROR: end of Tcl error block", eError);
|
||||||
}
|
}
|
||||||
DeleteDynString(command);
|
DeleteDynString(command);
|
||||||
if (SCGetInterrupt(pCon) >= eAbortBatch) {
|
if (SCGetInterrupt(pCon) >= eAbortBatch) {
|
||||||
|
2
lld.c
2
lld.c
@ -69,7 +69,7 @@ static int ListInit(int List, int ItemSize)
|
|||||||
if (0 != ItemSize) {
|
if (0 != ItemSize) {
|
||||||
/* create dummy head node
|
/* create dummy head node
|
||||||
*/
|
*/
|
||||||
Fortify_CheckAllMemory();
|
(void)Fortify_CheckAllMemory();
|
||||||
Tmp = NODE_MALLOC(List);
|
Tmp = NODE_MALLOC(List);
|
||||||
if (NULL == Tmp) {
|
if (NULL == Tmp) {
|
||||||
return ERR_MEMORY;
|
return ERR_MEMORY;
|
||||||
|
@ -28,6 +28,8 @@ typedef struct ScriptContext {
|
|||||||
ObjectDescriptor *desc;
|
ObjectDescriptor *desc;
|
||||||
ContextItem *nodes;
|
ContextItem *nodes;
|
||||||
ContextItem *trash;
|
ContextItem *trash;
|
||||||
|
Hdb *sendNode;
|
||||||
|
int sendCalled;
|
||||||
} ScriptContext;
|
} ScriptContext;
|
||||||
|
|
||||||
struct SctController {
|
struct SctController {
|
||||||
@ -152,7 +154,6 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
Hdb *cNode = NULL;
|
Hdb *cNode = NULL;
|
||||||
hdbValue v;
|
hdbValue v;
|
||||||
double dtime;
|
double dtime;
|
||||||
int iMacro;
|
|
||||||
|
|
||||||
assert(sct == object);
|
assert(sct == object);
|
||||||
if (sct->nodes != NULL) {
|
if (sct->nodes != NULL) {
|
||||||
@ -190,14 +191,13 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
* print
|
* print
|
||||||
*/
|
*/
|
||||||
if (strcmp(argv[1], "print") == 0) {
|
if (strcmp(argv[1], "print") == 0) {
|
||||||
iMacro = con->iMacro;
|
|
||||||
if (queueData != NULL) {
|
if (queueData != NULL) {
|
||||||
queueData->answered = 1;
|
queueData->answered = 1;
|
||||||
con->iMacro = queueData->inMacro; /* take macro flag stored at set callback */
|
SCsetMacro(con, queueData->inMacro); /* take macro flag stored at set callback */
|
||||||
}
|
}
|
||||||
Arg2Text(argc - 2, argv + 2, value, sizeof value);
|
Arg2Text(argc - 2, argv + 2, value, sizeof value);
|
||||||
SCWrite(con, value, eWarning);
|
SCWrite(con, value, eWarning);
|
||||||
con->iMacro = iMacro;
|
SCsetMacro(con, 1); /* where are always in Macro */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +223,19 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send command
|
||||||
|
*/
|
||||||
|
if (strcmp(argv[1], "send") == 0 && argc > 2) {
|
||||||
|
if (sct->sendNode != node) {
|
||||||
|
SCPrintf(con, eError, "ERROR: %s may be called only in action scripts",
|
||||||
|
argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sct->sendCalled = 1;
|
||||||
|
/* continue with property handling */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* property handling
|
* property handling
|
||||||
*/
|
*/
|
||||||
@ -265,6 +278,13 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
ret = Tcl_EvalEx(pTcl, script, l, 0);
|
ret = Tcl_EvalEx(pTcl, script, l, 0);
|
||||||
result = (char *) Tcl_GetStringResult(pTcl);
|
result = (char *) Tcl_GetStringResult(pTcl);
|
||||||
if (ret != TCL_OK && result[0] != '\0') {
|
if (ret != TCL_OK && result[0] != '\0') {
|
||||||
|
if (strncmp(result, "ERROR:", 6) == 0) {
|
||||||
|
/* remove "ERROR:", as it will be added later */
|
||||||
|
result += 6;
|
||||||
|
if (result[0] == ' ') {
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
SCPrintf(con, eLog, "error: %s", result);
|
SCPrintf(con, eLog, "error: %s", result);
|
||||||
}
|
}
|
||||||
@ -306,7 +326,9 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
char *emsg;
|
char *emsg;
|
||||||
size_t l;
|
size_t l;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
int ret;
|
||||||
char timeKey[50], timeVal[50];
|
char timeKey[50], timeVal[50];
|
||||||
|
int iMacro;
|
||||||
|
|
||||||
if (queueData != NULL && queueData->conCtx != NULL) {
|
if (queueData != NULL && queueData->conCtx != NULL) {
|
||||||
con = queueData->conCtx;
|
con = queueData->conCtx;
|
||||||
@ -325,9 +347,6 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
SetProp(node, controller->node, "state", state);
|
SetProp(node, controller->node, "state", state);
|
||||||
}
|
}
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
SetProp(node, controller->node, "sent",
|
|
||||||
GetProp(node, controller->node, "send"));
|
|
||||||
SetProp(node, controller->node, "send", NULL);
|
|
||||||
script = GetProp(node, controller->node, state);
|
script = GetProp(node, controller->node, state);
|
||||||
if (script == NULL)
|
if (script == NULL)
|
||||||
script = state;
|
script = state;
|
||||||
@ -339,11 +358,12 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
commError = 0;
|
commError = 0;
|
||||||
}
|
}
|
||||||
script = strdup(script);
|
script = strdup(script);
|
||||||
if (!SctCallInContext(con, script, node, controller, &result)) {
|
sct->sendNode = node;
|
||||||
|
sct->sendCalled = 0;
|
||||||
|
ret = SctCallInContext(con, script, node, controller, &result);
|
||||||
|
sct->sendNode = NULL;
|
||||||
|
if (ret == 0) {
|
||||||
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
||||||
if (strncmp(result, "ERROR: ", 7) == 0) {
|
|
||||||
result += 7;
|
|
||||||
}
|
|
||||||
emsg = GetHdbProp(node, eprop);
|
emsg = GetHdbProp(node, eprop);
|
||||||
if (emsg == NULL || con != controller->conn) {
|
if (emsg == NULL || con != controller->conn) {
|
||||||
GetHdbPath(node, path, sizeof path);
|
GetHdbPath(node, path, sizeof path);
|
||||||
@ -366,7 +386,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
sscanf(emsg, "%d", &cnt);
|
sscanf(emsg, "%d", &cnt);
|
||||||
}
|
}
|
||||||
cnt++;
|
cnt++;
|
||||||
snprintf(msg, sizeof msg, "%dx {%s} %s", cnt, origScript, result);
|
snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result);
|
||||||
SetHdbProperty(node, eprop, msg);
|
SetHdbProperty(node, eprop, msg);
|
||||||
send = NULL;
|
send = NULL;
|
||||||
free(script);
|
free(script);
|
||||||
@ -375,7 +395,12 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
state = result;
|
state = result;
|
||||||
if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) {
|
if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) {
|
||||||
if (queueData == data && !data->answered) {
|
if (queueData == data && !data->answered) {
|
||||||
SCWrite(con, "o.k.", eWarning);
|
if (queueData->inMacro == 0) {
|
||||||
|
iMacro = SCinMacro(con);
|
||||||
|
con->iMacro = 0;
|
||||||
|
SCWrite(con, "o.k.", eWarning);
|
||||||
|
SCsetMacro(con, iMacro);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
||||||
emsg = GetHdbProp(node, eprop);
|
emsg = GetHdbProp(node, eprop);
|
||||||
@ -396,8 +421,10 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
SetProp(node, controller->node, "state", state);
|
SetProp(node, controller->node, "state", state);
|
||||||
free(script);
|
free(script);
|
||||||
script = NULL;
|
script = NULL;
|
||||||
send = GetProp(node, controller->node, "send");
|
if (sct->sendCalled) {
|
||||||
if (send != NULL && send[0] != '\0') {
|
send = GetProp(node, controller->node, "send");
|
||||||
|
if (send == NULL)
|
||||||
|
send = "";
|
||||||
if (controller->verbose) {
|
if (controller->verbose) {
|
||||||
SCPrintf(con, eLog, "send : %s", send);
|
SCPrintf(con, eLog, "send : %s", send);
|
||||||
}
|
}
|
||||||
@ -522,6 +549,8 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
char *error;
|
char *error;
|
||||||
SConnection *con;
|
SConnection *con;
|
||||||
char path[MAX_HDB_PATH];
|
char path[MAX_HDB_PATH];
|
||||||
|
char *sicsCommand;
|
||||||
|
int iMacro;
|
||||||
|
|
||||||
pm = GetKillPtrMessage(msg);
|
pm = GetKillPtrMessage(msg);
|
||||||
if (pm != NULL) {
|
if (pm != NULL) {
|
||||||
@ -554,7 +583,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
if (script != NULL) {
|
if (script != NULL) {
|
||||||
if (SctCallInContext(con, script, node, data->controller, &error) ==
|
if (SctCallInContext(con, script, node, data->controller, &error) ==
|
||||||
0) {
|
0) {
|
||||||
SCPrintf(con, eError, "ERROR: %s", error);
|
SCPrintf(con, eError, "ERROR: in {%s}: %s", script, error);
|
||||||
SetHdbProperty(node, "target", NULL);
|
SetHdbProperty(node, "target", NULL);
|
||||||
return hdbAbort;
|
return hdbAbort;
|
||||||
}
|
}
|
||||||
@ -574,16 +603,19 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data->conCtx != NULL) {
|
if (data->conCtx != NULL) {
|
||||||
GetHdbPath(node, path, sizeof path);
|
if (data->inMacro == 0) {
|
||||||
SCPrintf(data->conCtx, eWarning,
|
GetHdbPath(node, path, sizeof path);
|
||||||
"%s target changed to %s before completion", path,
|
SCsetMacro(data->conCtx, 0);
|
||||||
GetCharArray(text));
|
SCPrintf(data->conCtx, eWarning,
|
||||||
|
"%s target changed to %s before completion", path,
|
||||||
|
GetCharArray(text));
|
||||||
|
}
|
||||||
SCDeleteConnection(data->conCtx);
|
SCDeleteConnection(data->conCtx);
|
||||||
}
|
}
|
||||||
DeleteDynString(text);
|
DeleteDynString(text);
|
||||||
data->conCtx = SCCopyConnection(con);
|
data->conCtx = SCCopyConnection(con);
|
||||||
data->answered = 0;
|
data->answered = 0;
|
||||||
data->inMacro = con->iMacro;
|
data->inMacro = SCinMacro(con);
|
||||||
DevQueue(data->controller->devser, data, prio,
|
DevQueue(data->controller->devser, data, prio,
|
||||||
SctWriteHandler, SctMatch, NULL);
|
SctWriteHandler, SctMatch, NULL);
|
||||||
/* no kill function in DevQueue: data is owned by the node (callback list) */
|
/* no kill function in DevQueue: data is owned by the node (callback list) */
|
||||||
@ -594,10 +626,20 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
if (mm != NULL) {
|
if (mm != NULL) {
|
||||||
if (queueData != NULL && queueData->conCtx != NULL && !data->answered) {
|
if (queueData != NULL && queueData->conCtx != NULL && !data->answered) {
|
||||||
/* update called from a write action */
|
/* update called from a write action */
|
||||||
data->answered = 1;
|
|
||||||
GetHdbPath(node, path, sizeof path);
|
|
||||||
text = formatValue(*(mm->v), node);
|
text = formatValue(*(mm->v), node);
|
||||||
SCPrintf(queueData->conCtx, eWarning, "OK: %s set to: %s", path, GetCharArray(text));
|
if (queueData->inMacro == 0 && queueData->node == node) {
|
||||||
|
data->answered = 1;
|
||||||
|
iMacro = SCinMacro(queueData->conCtx);
|
||||||
|
SCsetMacro(queueData->conCtx, 0);
|
||||||
|
sicsCommand = GetHdbProp(node, "sicscommand");
|
||||||
|
if (sicsCommand) {
|
||||||
|
SCPrintf(queueData->conCtx, eWarning, "OK: %s %s", sicsCommand, GetCharArray(text));
|
||||||
|
} else {
|
||||||
|
GetHdbPath(node, path, sizeof path);
|
||||||
|
SCPrintf(queueData->conCtx, eWarning, "OK: hset %s %s", path, GetCharArray(text));
|
||||||
|
}
|
||||||
|
SCsetMacro(queueData->conCtx, iMacro);
|
||||||
|
}
|
||||||
DeleteDynString(text);
|
DeleteDynString(text);
|
||||||
}
|
}
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
@ -1137,6 +1179,7 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SetHdbProperty(controller->node, "controllerName", objName);
|
SetHdbProperty(controller->node, "controllerName", objName);
|
||||||
|
SetHdbProperty(controller->node, "sicsdev", objName);
|
||||||
|
|
||||||
AddCommand(pServ->pSics, objName, InterInvokeSICSOBJ, KillSICSOBJ, ccmd);
|
AddCommand(pServ->pSics, objName, InterInvokeSICSOBJ, KillSICSOBJ, ccmd);
|
||||||
RegisterSICSOBJKillCmd(ccmd, objName);
|
RegisterSICSOBJKillCmd(ccmd, objName);
|
||||||
|
@ -381,6 +381,7 @@ int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics,
|
|||||||
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
|
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
|
||||||
RegisterSICSOBJKillCmd(pNew, argv[1]);
|
RegisterSICSOBJKillCmd(pNew, argv[1]);
|
||||||
}
|
}
|
||||||
|
SetHdbProperty(pNew->objectNode, "sicsdev", argv[1]);
|
||||||
status = AddCommand(pSics,
|
status = AddCommand(pSics,
|
||||||
argv[1], InterInvokeSICSOBJ, KillDriveOBJ, pNew);
|
argv[1], InterInvokeSICSOBJ, KillDriveOBJ, pNew);
|
||||||
if (status != 1) {
|
if (status != 1) {
|
||||||
|
@ -12,12 +12,38 @@
|
|||||||
|
|
||||||
#define MAX_HDB_PATH 1024
|
#define MAX_HDB_PATH 1024
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
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,
|
static int MakePlainNode(pHdb parent, char *name, SConnection * pCon,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
{
|
{
|
||||||
pHdb child = NULL;
|
pHdb child = NULL;
|
||||||
int type = 0, length = 0, priv = -1;
|
int type = 0, length = 0, priv = -1;
|
||||||
hdbValue val;
|
hdbValue val;
|
||||||
|
pDynString sicsCommand = NULL;
|
||||||
|
|
||||||
if (argc < 5) {
|
if (argc < 5) {
|
||||||
SCWrite(pCon, "ERROR: not enough arguments to create plain node",
|
SCWrite(pCon, "ERROR: not enough arguments to create plain node",
|
||||||
@ -68,6 +94,13 @@ static int MakePlainNode(pHdb parent, char *name, SConnection * pCon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddHipadabaChild(parent, child, pCon);
|
AddHipadabaChild(parent, child, pCon);
|
||||||
|
if (type != HIPNONE) {
|
||||||
|
sicsCommand = ComposeSicsCommand(child);
|
||||||
|
if (sicsCommand) {
|
||||||
|
SetHdbProperty(child, "sicscommand", GetCharArray(sicsCommand));
|
||||||
|
DeleteDynString(sicsCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
45
sicsobj.c
45
sicsobj.c
@ -351,40 +351,45 @@ static int isNodePrintable(pHdb node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void objFormatNode(pHdb node, pDynString data)
|
static void objFormatNode(pHdb node, char separator,
|
||||||
|
char *prefix, pDynString data)
|
||||||
{
|
{
|
||||||
char par[40];
|
char par[128];
|
||||||
pDynString val = NULL;
|
pDynString dyn = NULL;
|
||||||
|
int i;
|
||||||
|
pHdb child;
|
||||||
|
char *vis;
|
||||||
|
|
||||||
snprintf(par, 40, "%-20s = ", node->name);
|
snprintf(par, sizeof par, "%-20s = ", prefix);
|
||||||
DynStringConcat(data, par);
|
DynStringConcat(data, par);
|
||||||
val = formatValue(node->value, node);
|
dyn = formatValue(node->value, node);
|
||||||
if (val != NULL) {
|
if (dyn != NULL) {
|
||||||
DynStringConcat(data, GetCharArray(val));
|
DynStringConcat(data, GetCharArray(dyn));
|
||||||
DynStringConcatChar(data, '\n');
|
} else {
|
||||||
DeleteDynString(val);
|
dyn = CreateDynString(60, 63);
|
||||||
}
|
}
|
||||||
|
DynStringConcatChar(data, '\n');
|
||||||
|
for (child = node->child; child != NULL; child = child->next) {
|
||||||
|
DynStringCopy(dyn, prefix);
|
||||||
|
DynStringConcatChar(dyn, separator);
|
||||||
|
DynStringConcat(dyn, child->name);
|
||||||
|
objFormatNode(child, '/', GetCharArray(dyn), data);
|
||||||
|
}
|
||||||
|
DeleteDynString(dyn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int ListObj(pSICSOBJ self, SConnection * pCon, int argc,
|
static int ListObj(pSICSOBJ self, SConnection * pCon, int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
pHdb node = NULL;
|
|
||||||
pDynString data;
|
pDynString data;
|
||||||
|
|
||||||
data = CreateDynString(128, 128);
|
data = CreateDynString(128, 128);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
node = self->pDes->parNode;
|
if (self->pDes->parNode != NULL) {
|
||||||
if (node != NULL) {
|
objFormatNode(self->pDes->parNode, ' ', argv[0], data);
|
||||||
objFormatNode(node, data);
|
|
||||||
node = node->child;
|
|
||||||
while (node != NULL) {
|
|
||||||
objFormatNode(node, data);
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SCWrite(pCon, GetCharArray(data), eValue);
|
SCWrite(pCon, GetCharArray(data), eValue);
|
||||||
DeleteDynString(data);
|
DeleteDynString(data);
|
||||||
@ -440,7 +445,7 @@ int InvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
} else if (strcmp(argv[1], "list") == 0) {
|
} else if (strcmp(argv[1], "list") == 0) {
|
||||||
return ListObj(self, pCon, argc, argv);
|
return ListObj(self, pCon, argc, argv);
|
||||||
}
|
}
|
||||||
SCPrintf(pCon, eError, "ERROR: %s %s not found", argv[0], argv[1]);
|
/* error message written by the caller */
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -508,7 +513,7 @@ pSICSOBJ SetupSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
|
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHdbProperty(pNew->objectNode, "objectName", argv[1]);
|
SetHdbProperty(pNew->objectNode, "sicsdev", argv[1]);
|
||||||
status = AddCommand(pSics,
|
status = AddCommand(pSics,
|
||||||
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
||||||
if (status != 1) {
|
if (status != 1) {
|
||||||
|
Reference in New Issue
Block a user