From 217de95b297597ed5336ec699e4eebfac0ac349c Mon Sep 17 00:00:00 2001 From: zolliker Date: Wed, 13 Feb 2008 09:59:23 +0000 Subject: [PATCH] - minor fixes and improvements --- ascon.c | 24 +- ascon.h | 14 +- ascon.i | 12 +- conman.c | 5 + scriptcontext.c | 738 +++++++++++++++++------------------------------- 5 files changed, 294 insertions(+), 499 deletions(-) diff --git a/ascon.c b/ascon.c index 243ea0ee..72a6043d 100644 --- a/ascon.c +++ b/ascon.c @@ -57,7 +57,7 @@ double DoubleTime(void) { return now.tv_sec + now.tv_usec / 1e6; } -static void AsconError(AsconPtr a, char *msg, int errorno) { +static void AsconError(Ascon *a, char *msg, int errorno) { static char *stateText[]={ "state 0", "kill", "state 2", "notConnected", "connect", "start connect", "connect finished", "connect failed", @@ -80,7 +80,7 @@ static void AsconError(AsconPtr a, char *msg, int errorno) { a->state |= AsconFailed; } -static void AsconConnect(AsconPtr a) { +static void AsconConnect(Ascon *a) { /* input state: AsconConnectStart output state: AsconFailed or AsconConnecting */ int ret; @@ -124,7 +124,7 @@ static void AsconConnect(AsconPtr a) { return; } -void AsconStdInit(AsconPtr a, char *hostport) { +void AsconStdInit(Ascon *a, char *hostport) { a->fd = -1; a->state = AsconConnectStart; a->timeout = 2.0; /* sec */ @@ -245,7 +245,7 @@ int AsconWriteChars(int fd, char *data, int length) { static double lastCall = 0; -int AsconStdHandler(AsconPtr a) { +int AsconStdHandler(Ascon *a) { int ret; int l; char chr; @@ -354,7 +354,7 @@ void AsconInsertProtocol(AsconProtocol *protocol) { AsconProtocolAdd(&protocols, protocol); } -AsconHandler AsconSetHandler(AsconPtr a, int argc, char *argv[]) { +AsconHandler AsconSetHandler(Ascon *a, int argc, char *argv[]) { AsconProtocol *p; if (argc < 1) return NULL; @@ -378,8 +378,8 @@ char *ConcatArgs(int argc, char *argv[]) { return Arg2Tcl(argc, argv, NULL, -1); } -AsconPtr AsconMake(SConnection *con, int argc, char *argv[]) { - AsconPtr a; +Ascon *AsconMake(SConnection *con, int argc, char *argv[]) { + Ascon *a; char *args; a = calloc(1, sizeof(*a)); @@ -402,7 +402,7 @@ AsconPtr AsconMake(SConnection *con, int argc, char *argv[]) { return a; } -void AsconKill(AsconPtr a) { +void AsconKill(Ascon *a) { a->state = AsconKillMe; a->handler(a); if (a->fd > 0) { @@ -416,7 +416,7 @@ void AsconKill(AsconPtr a) { free(a); } -AsconStatus AsconTask(AsconPtr a) { +AsconStatus AsconTask(Ascon *a) { a->handler(a); while (1) { switch (a->state) { @@ -462,7 +462,7 @@ AsconStatus AsconTask(AsconPtr a) { } } -int AsconWrite(AsconPtr a, char *command, int noResponse) { +int AsconWrite(Ascon *a, char *command, int noResponse) { if (a->state <= AsconConnectFailed || a->state % 4 < AsconFinished) return 0; DynStringCopy(a->wrBuffer, command); a->noResponse = noResponse; @@ -472,7 +472,7 @@ int AsconWrite(AsconPtr a, char *command, int noResponse) { return 1; } -char *AsconRead(AsconPtr a) { +char *AsconRead(Ascon *a) { if (a->noResponse) { a->noResponse=0; return ""; @@ -488,6 +488,6 @@ char *AsconRead(AsconPtr a) { return NULL; } -ErrMsgList *AsconGetErrList(AsconPtr a) { +ErrMsgList *AsconGetErrList(Ascon *a) { return &a->errList; } diff --git a/ascon.h b/ascon.h index 55ae33ae..0378c211 100644 --- a/ascon.h +++ b/ascon.h @@ -10,7 +10,7 @@ /** \brief the asynchronous connection */ -typedef struct Ascon *AsconPtr; +typedef struct Ascon Ascon; /** \brief the possible results of AsconTask */ @@ -29,18 +29,18 @@ typedef enum { * are protocol specific, but argv[1] is usually host::port * \return the created connection or NULL on failure */ -AsconPtr AsconMake(SConnection *con, int argc, char *argv[]); +Ascon *AsconMake(SConnection *con, int argc, char *argv[]); /** \brief kill function * \param a the connection to be killed */ -void AsconKill(AsconPtr a); +void AsconKill(Ascon *a); /** \brief the task handler. To be called repeatedly. * \param a the connection * \return the state of the connection */ -AsconStatus AsconTask(AsconPtr a); +AsconStatus AsconTask(Ascon *a); /** \brief write to the connection. allowed only when the state is ascon_ready * \param a the connection @@ -48,7 +48,7 @@ AsconStatus AsconTask(AsconPtr a); * \param noResponse 0 normally, 1 if no reponse is expected * \return 1 on success, 0 when not ready */ -int AsconWrite(AsconPtr a, char *command, int noResponse); +int AsconWrite(Ascon *a, char *command, int noResponse); /** \brief read from the connection. allowed only when a response is available * \param a the connection @@ -58,12 +58,12 @@ int AsconWrite(AsconPtr a, char *command, int noResponse); * The result is only valid until the next call to other AsconXxx functions * and has to be duplicated if needed later. */ -char *AsconRead(AsconPtr a); +char *AsconRead(Ascon *a); /** \brief get the connections error list * \return the error list */ -ErrMsgList *AsconGetErrList(AsconPtr a); +ErrMsgList *AsconGetErrList(Ascon *a); /** \brief a helper function * \param argc the number of args diff --git a/ascon.i b/ascon.i index c941b184..a3f3b625 100644 --- a/ascon.i +++ b/ascon.i @@ -50,12 +50,12 @@ typedef enum { * * custom handlers must have this prototype */ -typedef int (* AsconHandler)(AsconPtr connection); +typedef int (* AsconHandler)(Ascon *connection); /** Ascon struct * all members are public, allowing access by handler wrappers */ -typedef struct Ascon { +struct Ascon { AsconState state; /**< the current state */ int fd; /**< socket */ int readState; /**< default implementation: 'was cr' */ @@ -70,7 +70,7 @@ typedef struct Ascon { int noResponse; /**< no response expected */ int responseValid; /**< a valid response is ready */ AsconHandler handler; /**< handler function */ -} Ascon; +}; #define ASCON_SELECT_ERROR -1 #define ASCON_RECV_ERROR -2 @@ -83,7 +83,7 @@ typedef struct Ascon { * * In most cases a custom handler may be a wrapper around AsconStdHandler */ -int AsconStdHandler(AsconPtr a); +int AsconStdHandler(Ascon *a); /** \brief initialize a standard connection * \param a the connection @@ -91,7 +91,7 @@ int AsconStdHandler(AsconPtr a); * * In most cases a custom init function may be a wrapper around AsconStdInit */ -void AsconStdInit(AsconPtr a, char *hostport); +void AsconStdInit(Ascon *a, char *hostport); /** The Ascon Protocol */ @@ -111,7 +111,7 @@ void AsconInsertProtocol(AsconProtocol *protocol); * \param a the connection to be closed * remark: the connection struct itself has to be freed manually */ -void AsconClose(AsconPtr a); +void AsconClose(Ascon *a); /** \brief swallow garbage (utility function) * \param fd the socket diff --git a/conman.c b/conman.c index 8f7aa792..f3888ec0 100644 --- a/conman.c +++ b/conman.c @@ -1040,6 +1040,11 @@ pDynString SCEndBuffering(SConnection *pCon) SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); + /* put it into the interpreter if present */ + if(SCinMacro(self)) + { + InterpWrite(pServ->pSics,buffer); + } return 1; } /*-------------------------------------------------------------------------- diff --git a/scriptcontext.c b/scriptcontext.c index 8f544afc..151a34c3 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -26,6 +26,7 @@ typedef enum { sct_path_keyword, sct_update_keyword, sct_take_keyword, + sct_get_keyword, sct_complete_keyword, sct_chain_keyword, sct_next_keyword, @@ -41,6 +42,7 @@ static char *sctKeywords[]={ "path", "update", "take", + "get", "complete", "chain", "next", @@ -56,7 +58,7 @@ typedef struct SctChain { struct SctChain *next; char *command; SctList *scriptList; - pHdb relatedNode; + char *relatedPath; ErrMsg *msg; int doit; char *dynamic; @@ -91,30 +93,25 @@ typedef struct Sct Sct; typedef struct SctParData { struct SctParData *next; Sct *sct; - SctChain *scriptChain; + SctChain *setChain; + SctChain *updateChain; int pending, inprogress; int refCnt; - hdbValue target; SCStore conCtx; } SctParData; -typedef struct SctObjectName { - struct SctObjectName *next; - char *name; -} SctObjectName; - -/* define SctObjectNameList and their functions */ -#define MC_NAME(T) SctObjectName##T -#include "mclist.c" +typedef struct SctNode { + struct SctNode *next; + pHdb node; +} SctNode; struct Sct { pObjectDescriptor desc; char *name; SctListList scriptLists; - SctObjectNameList names; /* created with the "object" command, needed for kill only */ - AsconPtr ascon; - pHdb currentNode; - SctParData *foundData; + Ascon *ascon; + char *currentPath; /* path for configuration (sct is owner) */ + char *relatedPath; /* node for scripts (chains are owner) */ char *cmd; char *result; char *nextScript; @@ -127,6 +124,7 @@ struct Sct { int killObj; int verbose; int taskSteps; + time_t maxAge; }; static Sct *sct = NULL; @@ -140,173 +138,6 @@ static void SctFreeParData(void *d) { } } -pHdb SctFindObjNode(char *name) { - CommandList *cmd; - pDummy obj; - - cmd = FindCommand(pServ->pSics, name); - if (cmd == NULL) return NULL; - obj = (void *)cmd->pData; - if (obj == NULL || obj->pDescriptor->parNode==NULL) return NULL; - return obj->pDescriptor->parNode; -} - -/** \brief find the node with the relative path relpath - * \param node the root node (where to start) - * \param relpath an absolute or relative path - * \param parentPtr a pointer to the found parent (may be NULL if not used) - * \param nodePtr a pointer to the found node - * \return the name of the node - * - * An abolute path starts with a slash, a relative path equal to "." - * means that the input node is returned. A syntax like "..", "../down" - * is also allowed, but the double dots must appear at the start of the path. - * - * This routine may also be used in order to find the parent node of - * a node not yet existing. In this case the nodePtr will point - * to a NULL pointer on return, and a pointer to the last element - * in the path is returned. - * - * Nodes anchored in the sics object list are also found when - * the path starts with "/sics/" - */ -char *SctFindNode(pHdb node, char *relpath, pHdb *parentPtr, pHdb *nodePtr) { - char *path; - char buffer[MAX_HDB_PATH]; - pHdb root = NULL; - char *name; - char *slash; - - if (strlen(relpath) >= sizeof(buffer)) { - *nodePtr = NULL; - return NULL; /* relpath too long */ - } - strcpy(buffer, relpath); - path = buffer; - if (path[0] == '/') { - if (strncmp(path, "/sics/", 6) == 0) { - /* sics object case */ - slash = strchr(path+6, '/'); - if (slash != NULL) { - *slash = '\0'; - } - node = SctFindObjNode(path); - if (node == NULL) goto notFound; - if (slash == NULL) goto nodeFound; - path = slash+1; - /* root node is sics object, path is relative to it */ - } else { - /* absolute path */ - node = GetHipadabaRoot(); - /* strip off first slash, root node is sics root */ - path++; - } - } else if (path[0] == '.') { - if (path[1] == '\0') { - /* this path */ - goto nodeFound; - } - /* upper node */ - while (strncmp(path, "..", 2) == 0 && node != NULL) { - node = node->mama; - if (path[2] == '\0') goto nodeFound; - path += 3; - } - if (node == NULL) goto notFound; - } - - /* now go down in path */ - while (node != NULL) { - root = node; - slash = strchr(path, '/'); - if (slash != NULL) *slash='\0'; - for (node = root->child; node != NULL; node = node->next) { - if (strcasecmp(node->name, path) == 0) { - if (slash == NULL) goto nodeFound; - path = slash + 1; - break; - } - } - } - - if (slash == NULL) { - if (parentPtr != NULL) { - *parentPtr = root; - } - *nodePtr = NULL; - /* the returned name must be taken from the end of relpath, as path is no longer valid */ - name = relpath + (path - buffer); - goto finish; - } -notFound: - node = NULL; -nodeFound: - *nodePtr = node; - if (node) { - if (parentPtr != NULL) { - *parentPtr = node->mama; - } - name = node->name; - } else { - if (parentPtr != NULL) { - *parentPtr = NULL; - } - name = NULL; - } -finish: - return name; -} - -/** \brief get the absolute path of a node anchored in the - * Hipadaba root or in a sics object - * \param nodeArg the input node - * \param path the result - * \param pathlen length of the result - * \return 1 on success, 0 on failure - */ -int SctGetPath(pHdb nodeArg, char *path, size_t pathlen) { - pHdb node, root; - int len, pos, l; - static char *sics="/sics"; - - /* determine path length and root node */ - root = nodeArg; - len = 0; - for (node = nodeArg; node != NULL; node = node->mama) { - len += strlen(node->name) + 1; - if (len >= pathlen) return 0; /* buffer overflow (may be recursize path?) */ - root = node; - } - - /* check root and add prefix */ - path[0]='\0'; - if (root != GetHipadabaRoot()) { /* not anchored in root */ - if (!FindCommand(pServ->pSics, root->name)) { - /* not a sicsobject, give up */ - path[0]='\0'; - return 0; - } - /* sics object case */ - l = strlen(sics); - len += l; - if (len >= pathlen) return 0; - strncpy(path, sics, l); - } - - /* build the path backwards */ - path[len]='\0'; - pos = len; - for (node = nodeArg; node != NULL; node = node->mama) { - len = strlen(node->name); - pos -= len; - assert(pos>0); - strncpy(path+pos, node->name, len); - pos--; - path[pos]='/'; - } - return 1; -} - static int UpdateNode(SConnection *con, ErrMsgList *e, pHdb node, int argc, char *argv[]) { hdbValue newValue; static char errtxt[512]; @@ -349,6 +180,7 @@ static SctChain *SctMakeChain(char *command) { sc->dynamic = NULL; sc->command = command; sc->scriptList = NULL; + sc->relatedPath = NULL; sc->msg = NULL; return sc; } @@ -376,7 +208,7 @@ static int SctUpdateCallback(void *user, void *conn, pHdb node, hdbValue value) if (data->inprogress) { if (data->sct->operation == sct_complete_keyword) { data->inprogress = 0; - SctGetPath(node, path, sizeof path); + GetHdbPath(node, path, sizeof path); con = SCStorePush(data->conCtx); str = formatValue(value, node); SCPrintf(con, eStatus, "%s = %s", path, @@ -393,10 +225,11 @@ static int SctSetCallback(void *user, void *conn, pHdb node, hdbValue value) { SConnection *oldCon; char path[MAX_HDB_PATH]; pDynString str; + pHdb target; - if (data->scriptChain) { + if (data->setChain) { if (data->pending) { - SctGetPath(node, path, sizeof path); + GetHdbPath(node, path, sizeof path); oldCon = SCStorePush(data->conCtx); str = formatValue(value, node); SCPrintf(oldCon, eStatus, "target of %s changed to %s", path, @@ -406,9 +239,12 @@ static int SctSetCallback(void *user, void *conn, pHdb node, hdbValue value) { } data->conCtx = SCSave(conn, data->conCtx); data->pending = 1; - SctSetDirty(data->scriptChain); - copyHdbValue(&value, &data->target); - return 0; + SctSetDirty(data->setChain); + target = GetHipadabaNode(node, "target"); + if (target) { + UpdateHipadabaPar(target, value, NULL); + } + return 1; } return 1; } @@ -416,20 +252,31 @@ static int SctSetCallback(void *user, void *conn, pHdb node, hdbValue value) { static int SctReadCallback(void *user, void *conn, pHdb node, hdbValue value) { SctParData *data = user; - data->sct->foundData = data; - if (data->sct->operation == sct_take_keyword && data->pending) { - data->pending = 0; - data->inprogress = 1; - return 0; - } + /* not used ? */ return 1; } +int SctCallDynamicScript(Sct *sct, char *name, char *script) { + SctList *sl; + SctChain *sc; + for (sl = sct->scriptLists.head; sl != NULL; sl = sl->next) { + for (sc = sl->chains.head; sc != NULL; sc = sc->next) { /* don't touch the list pos */ + if (sc->dynamic && strcasecmp(name, sc->dynamic) == 0) { + if (sc->command) free(sc->command); + sc->command = script; + return 1; + } + } + } + return 0; +} + static int SctExec(SConnection *con, SicsInterp *sics, void *object, int argc, char *argv[]) { SctKeyword keyword; SctList *sl; SctChain *sc; - pHdb node; + SctParData *data; + pHdb node, target; hdbValue newValue; pDynString result; char *args; @@ -495,11 +342,11 @@ static int SctExec(SConnection *con, SicsInterp *sics, void *object, int argc, c SCWrite(con, sct->cmd, eValue); goto success; case sct_path_keyword: - if (SctGetPath(sct->currentNode, path, sizeof path)) { - SCWrite(con, path, eValue); - } else { - SCWrite(con, "ERROR: node not anchored or path name too long", eInError); + if (sct->relatedPath == NULL) { + SCWrite(con, "ERROR: undefined current path", eInError); + goto quit; } + SCWrite(con, sct->relatedPath, eValue); goto success; case sct_complete_keyword: /* fall through */ @@ -508,29 +355,38 @@ static int SctExec(SConnection *con, SicsInterp *sics, void *object, int argc, c SCPrintf(con, eInError, "ERROR: should be: %s %s ", argv[0], argv[1]); goto quit; } - SctFindNode(sct->currentNode, argv[2], NULL, &node); - if (node == NULL) { - goto missingPar; - } + node = FindHdbNode(sct->relatedPath, argv[2], con); + if (node == 0) goto quit; return UpdateNode(con, AsconGetErrList(sct->ascon), node, argc-3, argv+3); + case sct_get_keyword: case sct_take_keyword: if (argc < 3) { - SCPrintf(con, eInError, "ERROR: should be: %s take ", argv[0]); + SCPrintf(con, eInError, "ERROR: should be: %s %s ", argv[0], argv[1]); goto quit; } - SctFindNode(sct->currentNode, argv[2], NULL, &node); - if (node == NULL) { - goto missingPar; - } + node = FindHdbNode(sct->relatedPath, argv[2], con); + if (node == 0) goto quit; memset(&newValue,0,sizeof(hdbValue)); - sct->foundData = NULL; - GetHipadabaPar(node, &newValue, con); - if (sct->foundData) { - cloneHdbValue(&sct->foundData->target, &newValue); + if (keyword == sct_take_keyword) { + data = FindHdbCallbackData(node, HCBUPDATE, SctUpdateCallback, sct); + result = NULL; + if (data) { + if (data->pending) { + data->pending = 0; + data->inprogress = 1; + } + target = GetHipadabaNode(node, "target"); + if (target) { + result = formatValue(target->value, node); + } + } + } else { + result = formatValue(node->value, node); + } + if (result == NULL) { + SCPrintf(con, eInError, "ERROR: %s has no target value", node->name); + goto quit; } - result = formatValue(newValue, node); - ReleaseHdbValue(&newValue); - if (result == NULL) goto noMemory; if (sct->verbose != 0) { dcon = SCStorePush(sct->debugConn); SCPrintf(dcon, eWarning, "result: %s", GetCharArray(result)); @@ -557,17 +413,11 @@ static int SctExec(SConnection *con, SicsInterp *sics, void *object, int argc, c SCPrintf(con, eInError, "ERROR: should be: %s chain