- added is_running to driveable ease objects - ighdriv.c: try <maxtry> times when status reply failes - ipsdriv.c: fix trainedTo parameter - reduced SEA version of SICS
371 lines
8.7 KiB
C
371 lines
8.7 KiB
C
/*---------------------------------------------------------------------------
|
|
arrobj.c
|
|
|
|
a array object based on pardef
|
|
|
|
Markus Zolliker, Feb 2006
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
#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 <name> [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");
|
|
}
|