/*--------------------------------------------------------------------------- arrobj.c a array object based on pardef Markus Zolliker, Feb 2006 ---------------------------------------------------------------------------- */ #include #include #include "sics.h" #include "splitter.h" #include "pardef.h" #include "initializer.h" typedef struct ArrayItem { struct ArrayItem *next; char *name; char *value; char *unit; } ArrayItem; typedef struct { ParData p; ArrayItem *items, *freeItems; char *saveFile; int logged; } ArrayObj; static ParClass arrayObjClass = { "array", sizeof(ArrayObj) }; typedef struct WrtObjContext { FILE *file; int pos; char filename[PATH_MAX]; } WrtObjContext; /*-----------------------------------------------------------------------*/ int WrtObjOpen(WrtObjContext * ctx, char *fileName) { int iret; char *slashpos; /* create a temporary file first */ slashpos = strrchr(fileName, '/'); if (slashpos == NULL) { ctx->pos = 0; } else { ctx->pos = slashpos - fileName + 1; } iret = snprintf(ctx->filename, sizeof(ctx->filename), "%.*s.%s", ctx->pos, fileName, fileName + ctx->pos); if (iret < 0 || iret >= sizeof(ctx->filename)) { return 0; } remove(ctx->filename); /* remove already existing temporary file */ ctx->file = fopen(ctx->filename, "w"); return ctx->file != NULL; } /*-----------------------------------------------------------------------*/ void WrtObj(WrtObjContext * ctx, char *objectName) { CommandList *pCom = NULL; Dummy *pDum = NULL; if (ctx) { pCom = FindCommand(pServ->pSics, objectName); if (pCom == NULL) { return; } pDum = pCom->pData; if (pDum != NULL) { pDum->pDescriptor->SaveStatus(pCom->pData, pCom->pName, ctx->file); } } } /*-----------------------------------------------------------------------*/ void WrtObjClose(WrtObjContext * ctx) { char finalName[PATH_MAX]; if (ctx) { fclose(ctx->file); snprintf(finalName, sizeof finalName, "%.*s%s", ctx->pos, ctx->filename, ctx->filename + ctx->pos + 1); rename(ctx->filename, finalName); } } /*----------------------------------------------------------------------------*/ static int ArrayExists(void *object, void *arg, int argc, char *argv[]) { ArrayObj *arr = ParCast(&arrayObjClass, object); ArrayItem *item; assert(arr); if (argc == 1) { for (item = arr->items; item != NULL; item = item->next) { if (strcasecmp(argv[0], item->name) == 0) { ParPrintf(object, eValue, "1"); return 1; } } } ParPrintf(object, eValue, "0"); return 1; } /*----------------------------------------------------------------------------*/ static int ArrayItems(void *object, void *arg, int argc, char *argv[]) { ArrayObj *arr = ParCast(&arrayObjClass, object); ArrayItem *item; int l; char *result, *p; assert(arr); l = 1; for (item = arr->items; item != NULL; item = item->next) { l += strlen(item->name); l++; } result = calloc(l, 1); if (result) { p = result; for (item = arr->items; item != NULL; item = item->next) { strcpy(p, item->name); p += strlen(item->name); *p = ' '; p++; } if (p > result) p--; *p = '\0'; ParPrintf(object, eValue, "%s", result); free(result); } return 1; } /*----------------------------------------------------------------------------*/ static int ArrayMakeItem(void *object, void *delete, int argc, char *argv[]) /* make or delete */ { ArrayObj *arr = ParCast(&arrayObjClass, object); ArrayItem *item, **last; int iarg; assert(arr); if (argc < 1) goto Usage; /* missing check for user privilege */ last = &arr->items; for (item = arr->items; item != NULL; item = item->next) { if (strcasecmp(argv[0], item->name) == 0) { if (delete) { *last = item->next; /* remove item from list */ item->next = arr->freeItems; arr->freeItems = item; ParKillPar(arr, item->name); return 1; } break; } last = &item->next; } if (delete) { ParPrintf(object, eError, "ERROR: %s.%s not found", arr->p.name, argv[0]); return 0; } if (item == NULL) { if (arr->freeItems) { item = arr->freeItems; arr->freeItems = item->next; if (item->name) { free(item->name); item->name = NULL; } item->next = NULL; *last = item; } else { item = calloc(1, sizeof(ArrayItem)); if (item == NULL) return 0; *last = item; item->next = NULL; item->unit = NULL; item->value = NULL; } } if (item->unit) { free(item->unit); item->unit = NULL; } if (item->value) { free(item->value); item->value = NULL; } if (item->name != NULL) { if (0 != strcmp(item->name, argv[0])) { free(item->name); item->name = strdup(argv[0]); } } else { item->name = strdup(argv[0]); } iarg = 1; if (iarg < argc) { if (argv[iarg] && argv[iarg][0]) { item->value = argv[iarg]; } iarg++; if (iarg < argc) { if (argv[iarg] && argv[iarg][0]) { item->unit = argv[iarg]; } iarg++; if (iarg < argc) goto Usage; } } if (item->unit) item->unit = strdup(item->unit); if (item->value) item->value = strdup(item->value); ParInitPar(object, item->name, arr->logged); SCparChange(arr->p.conn); return 1; Usage: ParPrintf(object, eError, "Usage: %s makeitem [value] [unit]", arr->p.name); return 0; } /*----------------------------------------------------------------------------*/ static void ArrayObjParDef(void *object) { ArrayObj *arr = ParCast(&arrayObjClass, object); FILE *saveFile; ArrayItem *item, *next; char *u, *v; WrtObjContext context; static int doNotNest = 0; int saveObjects; saveFile = ParSaveFile(); if (!doNotNest && saveFile && arr->saveFile && *arr->saveFile) { saveObjects = WrtObjOpen(&context, arr->saveFile); } else { saveObjects = 0; } for (item = arr->items; item != NULL; item = item->next) { if (saveFile) { if (item->unit) { u = item->unit; } else { u = ""; } if (item->value) { v = item->value; } else { v = ""; } if (strchr(v, '\n') != NULL) { fprintf(saveFile, "%s makeitem %s {%s} \"%s\"\n", arr->p.name, item->name, v, u); } else { fprintf(saveFile, "%s makeitem %s \"%s\" \"%s\"\n", arr->p.name, item->name, v, u); } if (saveObjects) { WrtObj(&context, item->name); } } ParName(item->name); if (!arr->logged) { ParLogAs(NULL); } ParSave(2); ParAccess(usUser); if (item->unit) { ParTail(item->unit); } else { ParList(NULL); } ParStr(&item->value, ""); } if (saveObjects) { doNotNest = 1; WrtObj(&context, arr->p.name); doNotNest = 0; WrtObjClose(&context); } ParName("makeitem"); ParAccess(usUser); ParCmd(ArrayMakeItem, NULL); ParName("deleteitem"); ParAccess(usUser); ParCmd(ArrayMakeItem, "del"); ParName("exists"); ParAccess(usSpy); ParCmd(ArrayExists, NULL); ParName("items"); ParAccess(usSpy); ParCmd(ArrayItems, NULL); ParName("saveFile"); ParLogAs(NULL); ParAccess(usUser); ParStr(&arr->saveFile, ""); ParStdDef(); if (ParActionIs(PAR_KILL)) { for (item = arr->items; item != NULL; item = next) { next = item->next; ParKillPar(arr, item->name); if (item->name) free(item->name); if (item->unit) free(item->unit); if (item->value) free(item->value); free(item); } for (item = arr->freeItems; item != NULL; item = next) { next = item->next; if (item->name) free(item->name); if (item->unit) free(item->unit); if (item->value) free(item->value); free(item); } } } /*----------------------------------------------------------------------------*/ static int ArrayObjInit(SConnection * con, int argc, char *argv[], int dynamic) { ArrayObj *arr = NULL; char *creationCmd = NULL; if (dynamic) { creationCmd = Arg2Tcl(argc, argv, NULL, 0); } arr = ParMake(con, argv[1], &arrayObjClass, ArrayObjParDef, creationCmd); if (argc > 3 && strcasecmp(argv[3], "logged") == 0) { arr->logged = 1; } else { arr->logged = 0; } arr->freeItems = NULL; arr->items = NULL; return arr != NULL; } /*----------------------------------------------------------------------------*/ void ArrayObjStartup(void) { ParMakeClass(&arrayObjClass, NULL); MakeDriver("array", ArrayObjInit, 0, "String Array Object"); }