#include #include #include #include #include "sics.h" #include "sicsobj.h" #include "initializer.h" #include "commandlog.h" #include "hipadaba.h" #include "sicshipadaba.h" #include "dynstring.h" #include "ascon.h" #include "errormsg.h" /** \file * \brief script context implementation (Sct) */ /** \brief the maximum hdb path length */ #define MAX_HDB_PATH 1024 typedef enum { sct_send_keyword, sct_result_keyword, sct_command_keyword, sct_path_keyword, sct_update_keyword, sct_take_keyword, sct_get_keyword, sct_complete_keyword, sct_retry_keyword, sct_chain_keyword, sct_next_keyword, sct_steplist_keyword, sct_no_keyword } SctKeyword; /* keywords must have the same order as SctKeyword */ static char *sctKeywords[]={ "send", "result", "command", "path", "update", "take", "get", "complete", "retry", "chain", "next", "steplist", NULL }; static char *reset_type=""; typedef struct SctList SctList; typedef struct SctChain { struct SctChain *next; char *command; SctList *scriptList; char *relatedPath; ErrMsg *msg; int doit; char *dynamic; } SctChain; /* define SctChainList and their functions */ #define MC_NAME(T) SctChain##T #include "mclist.c" typedef enum {set_type, timed_type, manual_type, no_type} SctScriptListType; static char *slTypes[]={"set", "timed", "manual", NULL}; struct SctList { struct SctList *next; char *name; SctChain *beginScript; SctChain *endScript; SctScriptListType type; int dirty; double interval; double lastPeriod; SctChain *lastScript; SctChainList chains; }; /* define SctListList and their functions */ #define MC_NAME(T) SctList##T #include "mclist.c" typedef struct Sct Sct; typedef struct SctParData { struct SctParData *next; Sct *sct; SctChain *setChain; SctChain *updateChain; int pending, inprogress; int refCnt; SCStore conCtx; } SctParData; typedef struct SctNode { struct SctNode *next; pHdb node; } SctNode; struct Sct { pObjectDescriptor desc; char *name; SctListList scriptLists; Ascon *ascon; char *currentPath; /* path for configuration (sct is owner) */ char *relatedPath; /* node for scripts (chains are owner) */ char *cmd; char *result; char *nextScript; SctChain *runningChain; int tryCnt; SCStore debugConn; char *debugCommand; int sent; SctKeyword operation; int killTask; int killObj; int verbose; int taskSteps; time_t maxAge; }; static Sct *sct = NULL; static void SctFreeParData(void *d) { SctParData *data=d; data->refCnt--; if (data->refCnt == 0) { if (data->conCtx) SCStoreFree(data->conCtx); free(data); } } static int UpdateNode(SConnection *con, ErrMsgList *e, pHdb node, int argc, char *argv[]) { hdbValue newValue; static char errtxt[512]; char *str; int status; if (!cloneHdbValue(&node->value, &newValue)) { ErrPutMsg(e, NULL, "no memory"); return 0; } str = ConcatArgs(argc, argv); if (str == NULL) { ErrPutMsg(e, NULL, "no memory"); return 0; } if (!readHdbValue(&newValue, str, errtxt, sizeof errtxt)) { ErrPutMsg(e, errtxt, "conversion failure"); return 0; } free(str); status = UpdateHipadabaPar(node, newValue, con); ReleaseHdbValue(&newValue); return status; } static int SctFindKeyword(char *name, char *keywords[]) { int i; for (i=0; keywords[i]!=NULL; i++) { if (strcasecmp(name, keywords[i]) == 0) return i; } return i; } static SctChain *SctMakeChain(char *command) { SctChain *sc; sc = calloc(1, sizeof(*sc)); if (sc == NULL) return NULL; sc->doit = 0; sc->dynamic = NULL; sc->command = command; sc->scriptList = NULL; sc->relatedPath = NULL; sc->msg = NULL; return sc; } static void SctSetListDirty(SctList *sl) { if (!sl->dirty) { sl->dirty = 1; if (sl->beginScript) { sl->beginScript->doit = 1; } } } static void SctSetDirty(SctChain *sc) { SctSetListDirty(sc->scriptList); sc->doit = 1; } static int SctUpdateCallback(void *user, void *conn, pHdb node, hdbValue value) { SctParData *data = user; SConnection *con; char path[MAX_HDB_PATH]; pDynString str; if (data->inprogress) { if (data->sct->operation == sct_complete_keyword) { data->inprogress = 0; GetHdbPath(node, path, sizeof path); con = SCStorePush(data->conCtx); str = formatValue(value, node); SCPrintf(con, eStatus, "%s = %s", path, GetCharArray(str)); DeleteDynString(str); SCStorePop(data->conCtx); } } return 1; } static int SctSetCallback(void *user, void *conn, pHdb node, hdbValue value) { SctParData *data = user; SConnection *oldCon; char path[MAX_HDB_PATH]; pDynString str; pHdb target; if (data->setChain) { if (data->pending) { GetHdbPath(node, path, sizeof path); oldCon = SCStorePush(data->conCtx); str = formatValue(value, node); SCPrintf(oldCon, eStatus, "target of %s changed to %s", path, GetCharArray(str)); DeleteDynString(str); SCStorePop(data->conCtx); } data->conCtx = SCSave(conn, data->conCtx); data->pending = 1; SctSetDirty(data->setChain); target = GetHipadabaNode(node, "target"); if (target) { UpdateHipadabaPar(target, value, NULL); } return 1; } return 1; } static int SctReadCallback(void *user, void *conn, pHdb node, hdbValue value) { SctParData *data = user; /* 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; SctParData *data; pHdb node, target; hdbValue newValue; pDynString result; char *args; char path[MAX_HDB_PATH]; SConnection *dcon; if (sct == NULL) { SCPrintf(con, eError, "ERROR: %s may be called only in proper context", argv[0]); return 0; }; if (argc < 2) { SCPrintf(con, eInError, "ERROR: missing %s subcommand", argv[0]); goto quit; }; if (sct->verbose != 0) { args = ConcatArgs(argc, argv); dcon = SCStorePush(sct->debugConn); SCPrintf(dcon, eWarning, "commnd: %s", args); SCStorePop(sct->debugConn); free(args); args = NULL; } keyword = SctFindKeyword(argv[1], sctKeywords); sct->operation = keyword; switch (keyword) { case sct_send_keyword: if (argc < 4) { SCPrintf(con, eInError, "ERROR: should be: %s send