
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c Conflicts: .gitignore SICSmain.c asynnet.c confvirtualmot.c counter.c devexec.c drive.c event.h exebuf.c exeman.c histmem.c interface.h motor.c motorlist.c motorsec.c multicounter.c napi.c napi.h napi4.c network.c nwatch.c nxscript.c nxxml.c nxxml.h ofac.c reflist.c scan.c sicshipadaba.c sicsobj.c site_ansto/docs/Copyright.txt site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl statusfile.c tasdrive.c tasub.c tasub.h tasublib.c tasublib.h
585 lines
15 KiB
C
585 lines
15 KiB
C
/*
|
|
A module for displaying various bits of information about SICS
|
|
internals and objects.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, January 2006
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <tcl.h>
|
|
#include "sicslist.h"
|
|
#include "lld.h"
|
|
#include "lld_str.h"
|
|
/*------------------------------------------------------------------*/
|
|
static void listAllObjects(SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
Tcl_DString lst;
|
|
|
|
Tcl_DStringInit(&lst);
|
|
|
|
pCom = pSics->pCList;
|
|
while (pCom != NULL) {
|
|
Tcl_DStringAppend(&lst, pCom->pName, -1);
|
|
pCom = pCom->pNext;
|
|
Tcl_DStringAppend(&lst, ",", -1);
|
|
}
|
|
Tcl_DStringAppend(&lst, "ENDLIST", -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&lst), eValue);
|
|
Tcl_DStringFree(&lst);
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static void listAllObjectData(SConnection * pCon, char *name, pDummy data)
|
|
{
|
|
Tcl_DString lst;
|
|
char buffer[256];
|
|
IPair *prop = NULL;
|
|
|
|
Tcl_DStringInit(&lst);
|
|
if (data == NULL) {
|
|
snprintf(buffer, 255, "%s = command, ", name);
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
} else {
|
|
snprintf(buffer, 255, "%s=obj, ", name);
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
snprintf(buffer, 255, "type=%s, ", data->pDescriptor->name);
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
if (data->pDescriptor->GetInterface(data, DRIVEID) != NULL) {
|
|
snprintf(buffer, 255, "drivable=true, ");
|
|
} else {
|
|
snprintf(buffer, 255, "drivable=false, ");
|
|
}
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
if (data->pDescriptor->GetInterface(data, COUNTID) != NULL) {
|
|
snprintf(buffer, 255, "countable=true, ");
|
|
} else {
|
|
snprintf(buffer, 255, "countable=false, ");
|
|
}
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
if (data->pDescriptor->GetInterface(data, CALLBACKINTERFACE) != NULL) {
|
|
snprintf(buffer, 255, "callback=true, ");
|
|
} else {
|
|
snprintf(buffer, 255, "callback=false, ");
|
|
}
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
if (data->pDescriptor->GetInterface(data, ENVIRINTERFACE) != NULL) {
|
|
snprintf(buffer, 255, "environment=true, ");
|
|
} else {
|
|
snprintf(buffer, 255, "environment=false, ");
|
|
}
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
prop = data->pDescriptor->pKeys;
|
|
while (prop != NULL) {
|
|
snprintf(buffer, 255, "%s=%s, ", prop->name, prop->value);
|
|
Tcl_DStringAppend(&lst, buffer, -1);
|
|
prop = prop->pNext;
|
|
}
|
|
}
|
|
Tcl_DStringAppend(&lst, "ENDLIST", -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&lst), eValue);
|
|
Tcl_DStringFree(&lst);
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int getObjectData(pDummy obj, char *key, char buffer[512])
|
|
{
|
|
char *ptr = NULL;
|
|
void *iPtr = NULL;
|
|
int status = 0;
|
|
|
|
/*
|
|
* first check attributes
|
|
*/
|
|
ptr = IFindOption(obj->pDescriptor->pKeys, key);
|
|
if (ptr != NULL) {
|
|
snprintf(buffer, 511, "%s", ptr);
|
|
return 1;
|
|
}
|
|
/*
|
|
* check indirect attributes
|
|
*/
|
|
strtolower(key);
|
|
if (strcmp(key, "type") == 0) {
|
|
snprintf(buffer, 511, "%s", obj->pDescriptor->name);
|
|
return 1;
|
|
} else if (strcmp(key, "drivable") == 0) {
|
|
iPtr = obj->pDescriptor->GetInterface(obj, DRIVEID);
|
|
if (iPtr != NULL) {
|
|
status = 1;
|
|
snprintf(buffer, 511, "true");
|
|
} else {
|
|
status = 0;
|
|
snprintf(buffer, 511, "false");
|
|
}
|
|
} else if (strcmp(key, "countable") == 0) {
|
|
iPtr = obj->pDescriptor->GetInterface(obj, COUNTID);
|
|
if (iPtr != NULL) {
|
|
status = 1;
|
|
snprintf(buffer, 511, "true");
|
|
} else {
|
|
status = 0;
|
|
snprintf(buffer, 511, "false");
|
|
}
|
|
} else if (strcmp(key, "callback") == 0) {
|
|
iPtr = obj->pDescriptor->GetInterface(obj, CALLBACKINTERFACE);
|
|
if (iPtr != NULL) {
|
|
status = 1;
|
|
snprintf(buffer, 511, "true");
|
|
} else {
|
|
status = 0;
|
|
snprintf(buffer, 511, "false");
|
|
}
|
|
} else if (strcmp(key, "environment") == 0) {
|
|
iPtr = obj->pDescriptor->GetInterface(obj, ENVIRINTERFACE);
|
|
if (iPtr != NULL) {
|
|
status = 1;
|
|
snprintf(buffer, 511, "true");
|
|
} else {
|
|
status = 0;
|
|
snprintf(buffer, 511, "false");
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int printObjectData(SConnection * pCon, pDummy obj, char *key)
|
|
{
|
|
char value[512];
|
|
char buffer[1024];
|
|
int status;
|
|
|
|
status = getObjectData(obj, key, value);
|
|
if (status >= 0) {
|
|
snprintf(buffer, 1023, "%s=%s", key, value);
|
|
} else {
|
|
snprintf(buffer, 1023, "%s=UNDEFINED", key);
|
|
}
|
|
SCWrite(pCon, buffer, eValue);
|
|
if (status < 0) {
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static int existsObjectData(SConnection * pCon, pDummy obj, char *key)
|
|
{
|
|
char *ptr = NULL;
|
|
ptr = IFindOption(obj->pDescriptor->pKeys, key);
|
|
if (ptr != NULL)
|
|
SCPrintf(pCon, eValue, "%s", "true");
|
|
else
|
|
SCPrintf(pCon, eValue, "%s", "false");
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------
|
|
* this function implements a set on top of a list. This means that
|
|
* the list is first searched for the occurence of name. name is only
|
|
* added when it does not exist in list
|
|
* ----------------------------------------------------------------*/
|
|
static void addItemToList(int list, char *name)
|
|
{
|
|
int status;
|
|
char *pPtr = NULL;
|
|
|
|
status = LLDnodePtr2First(list);
|
|
while (status != 0) {
|
|
pPtr = (char *) LLDnodePtr(list);
|
|
if (pPtr != NULL) {
|
|
if (strcmp(pPtr, name) == 0) {
|
|
return;
|
|
}
|
|
}
|
|
status = LLDnodePtr2Next(list);
|
|
}
|
|
LLDstringAppend(list, name);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static void listToString(int list, Tcl_DString * txt)
|
|
{
|
|
int status;
|
|
char *pPtr = NULL;
|
|
|
|
status = LLDnodePtr2First(list);
|
|
while (status != 0) {
|
|
pPtr = (char *) LLDnodePtr(list);
|
|
if (pPtr != NULL) {
|
|
Tcl_DStringAppend(txt, pPtr, -1);
|
|
Tcl_DStringAppend(txt, ",", -1);
|
|
}
|
|
status = LLDnodePtr2Next(list);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
static void printKeyTypes(SicsInterp * pSics, SConnection * pCon,
|
|
char *key)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
int list;
|
|
int status;
|
|
char value[512];
|
|
Tcl_DString result;
|
|
|
|
if (strcmp(key, "interface") == 0) {
|
|
SCWrite(pCon, "drivable, countable, callback, environment", eValue);
|
|
return;
|
|
}
|
|
|
|
list = LLDstringCreate();
|
|
Tcl_DStringInit(&result);
|
|
pCom = pSics->pCList;
|
|
while (pCom != NULL) {
|
|
status = getObjectData((pDummy) pCom->pData, key, value);
|
|
if (status >= 0) {
|
|
addItemToList(list, value);
|
|
}
|
|
pCom = pCom->pNext;
|
|
}
|
|
LLDstringAppend(list, "ENDLIST");
|
|
|
|
listToString(list, &result);
|
|
SCWrite(pCon, Tcl_DStringValue(&result), eValue);
|
|
Tcl_DStringFree(&result);
|
|
LLDstringDelete(list);
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
static void printObjectsMatchingKeyVal(SicsInterp * pSics,
|
|
SConnection * pCon, char *key,
|
|
char *value)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
Tcl_DString result;
|
|
int status;
|
|
char buffer[512];
|
|
|
|
Tcl_DStringInit(&result);
|
|
pCom = pSics->pCList;
|
|
strtolower(value);
|
|
while (pCom != NULL) {
|
|
if (strcmp(key, "interface") == 0) {
|
|
status = getObjectData((pDummy) pCom->pData, value, buffer);
|
|
} else {
|
|
status = getObjectData((pDummy) pCom->pData, key, buffer);
|
|
if (status == 1) {
|
|
strtolower(buffer);
|
|
if (strcmp(buffer, value) == 0) {
|
|
status = 1;
|
|
} else {
|
|
status = 0;
|
|
}
|
|
}
|
|
}
|
|
if (status == 1) {
|
|
Tcl_DStringAppend(&result, pCom->pName, -1);
|
|
Tcl_DStringAppend(&result, ",", -1);
|
|
}
|
|
pCom = pCom->pNext;
|
|
}
|
|
Tcl_DStringAppend(&result, "ENDLIST", -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&result), eValue);
|
|
Tcl_DStringFree(&result);
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
static int setAttribute(SConnection * pCon, SicsInterp * pSics,
|
|
char *obj, char *key, char *value)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = NULL;
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
strtolower(key);
|
|
if (strcmp(key, "type") == 0 || strcmp(key, "interface") == 0) {
|
|
SCWrite(pCon, "ERROR: this key is forbidden", eError);
|
|
return 0;
|
|
}
|
|
|
|
pCom = FindCommand(pSics, obj);
|
|
if (pCom == NULL) {
|
|
SCWrite(pCon, "ERROR: object not found", eError);
|
|
return 0;
|
|
}
|
|
pDum = (pDummy) pCom->pData;
|
|
|
|
if (pDum != NULL) {
|
|
if (IFindOption(pDum->pDescriptor->pKeys, key) == NULL) {
|
|
pDum->pDescriptor->pKeys = IFAddOption(pDum->pDescriptor->pKeys,
|
|
key, value);
|
|
} else {
|
|
IFSetOption(pDum->pDescriptor->pKeys, key, value);
|
|
}
|
|
}
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int printObjStatus(SConnection * pCon, SicsInterp * pSics,
|
|
char *name)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
pICountable pCount = NULL;
|
|
pEVInterface pEV = NULL;
|
|
int status = -1, evStatus = -1;
|
|
char buffer[256];
|
|
|
|
pCom = FindCommand(pSics, name);
|
|
if (pCom == NULL) {
|
|
SCWrite(pCon, "ERROR: object not found", eError);
|
|
return 0;
|
|
}
|
|
pDum = (pDummy) pCom->pData;
|
|
if (pDum != NULL) {
|
|
pDriv = GetDrivableInterface(pDum);
|
|
if (pDriv != NULL) {
|
|
status = pDriv->CheckStatus(pDum, pCon);
|
|
}
|
|
pCount = GetCountableInterface(pDum);
|
|
if (pCount != NULL) {
|
|
status = pCount->CheckCountStatus(pDum, pCon);
|
|
}
|
|
pEV = pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE);
|
|
if (pEV != NULL) {
|
|
evStatus = pEV->IsInTolerance(pDum);
|
|
}
|
|
}
|
|
switch (status) {
|
|
case HWBusy:
|
|
snprintf(buffer, 255, "%s = running", pCom->pName);
|
|
break;
|
|
case HWIdle:
|
|
case OKOK:
|
|
if (evStatus < 0) {
|
|
snprintf(buffer, 255, "%s = idle", pCom->pName);
|
|
} else if (evStatus == 1) {
|
|
snprintf(buffer, 255, "%s = intolerance", pCom->pName);
|
|
} else {
|
|
snprintf(buffer, 255, "%s = outoftolerance", pCom->pName);
|
|
}
|
|
break;
|
|
case HWFault:
|
|
case HWPosFault:
|
|
snprintf(buffer, 255, "%s = faulty", pCom->pName);
|
|
break;
|
|
case HWPause:
|
|
snprintf(buffer, 255, "%s = paused", pCom->pName);
|
|
break;
|
|
case HWNoBeam:
|
|
snprintf(buffer, 255, "%s = nobeam", pCom->pName);
|
|
break;
|
|
default:
|
|
snprintf(buffer, 255, "%s = nostatus", pCom->pName);
|
|
break;
|
|
}
|
|
SCWrite(pCon, buffer, eValue);
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int printServer(SConnection * pCon)
|
|
{
|
|
Tcl_DString txt;
|
|
IPair *current = NULL;
|
|
char buffer[512];
|
|
|
|
Tcl_DStringInit(&txt);
|
|
current = pSICSOptions;
|
|
while (current != NULL) {
|
|
snprintf(buffer, 511, "%s=%s, ", current->name, current->value);
|
|
Tcl_DStringAppend(&txt, buffer, -1);
|
|
current = current->pNext;
|
|
}
|
|
Tcl_DStringAppend(&txt, "ENDLIST", -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&txt), eValue);
|
|
Tcl_DStringFree(&txt);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int printObjectPar(SConnection * pCon, SicsInterp * pSics,
|
|
char *obj)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
FILE *fd = NULL;
|
|
char *buffer = NULL, tmpfile[80];
|
|
pDummy pDum = NULL;
|
|
long length;
|
|
struct stat statbuf;
|
|
|
|
snprintf(tmpfile, 80, "SICS%6.6d.dat", getpid());
|
|
pCom = FindCommand(pSics, obj);
|
|
if (pCom == NULL) {
|
|
SCWrite(pCon, "ERROR: object to list not found", eError);
|
|
return 0;
|
|
}
|
|
fd = fopen(tmpfile, "w");
|
|
if (fd == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to open tmpfile", eError);
|
|
return 0;
|
|
}
|
|
pDum = (pDummy) pCom->pData;
|
|
if (pDum != NULL) {
|
|
pDum->pDescriptor->SaveStatus(pDum, obj, fd);
|
|
fclose(fd);
|
|
stat(tmpfile, &statbuf);
|
|
length = statbuf.st_size;
|
|
fd = fopen(tmpfile, "r");
|
|
if (fd == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to open tmpfile", eError);
|
|
return 0;
|
|
}
|
|
buffer = malloc(length + 1);
|
|
if (buffer == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in list par", eError);
|
|
fclose(fd);
|
|
unlink(tmpfile);
|
|
return 0;
|
|
}
|
|
memset(buffer, 0, length + 1);
|
|
fread(buffer, length, 1, fd);
|
|
fclose(fd);
|
|
SCWrite(pCon, buffer, eValue);
|
|
free(buffer);
|
|
unlink(tmpfile);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
extern int match(const char *mask, const char *name); /* from wwildcard.c */
|
|
|
|
static void printMatch(SConnection * pCon, SicsInterp * pSics, char *mask)
|
|
{
|
|
CommandList *current = NULL;
|
|
Tcl_DString txt;
|
|
|
|
Tcl_DStringInit(&txt);
|
|
current = pSics->pCList;
|
|
while (current != NULL) {
|
|
if (!match(mask, current->pName)) {
|
|
Tcl_DStringAppend(&txt, current->pName, -1);
|
|
Tcl_DStringAppend(&txt, ",", -1);
|
|
}
|
|
current = current->pNext;
|
|
}
|
|
Tcl_DStringAppend(&txt, "ENDLIST", -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&txt), eValue);
|
|
Tcl_DStringFree(&txt);
|
|
}
|
|
|
|
/*==================================================================*/
|
|
int SicsList(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
CommandList *pCom = NULL;
|
|
|
|
if (argc < 2) {
|
|
listAllObjects(pCon, pSics);
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(argv[1], "objstatus") == 0) {
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments to status",
|
|
eError);
|
|
return 0;
|
|
}
|
|
return printObjStatus(pCon, pSics, argv[2]);
|
|
}
|
|
|
|
if (strcmp(argv[1], "server") == 0) {
|
|
printServer(pCon);
|
|
return 1;
|
|
}
|
|
|
|
if (strcmp(argv[1], "par") == 0) {
|
|
if (argc > 2) {
|
|
return printObjectPar(pCon, pSics, argv[2]);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: not enough arguments to list par", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "match") == 0) {
|
|
if (argc > 2) {
|
|
printMatch(pCon, pSics, argv[2]);
|
|
return 1;
|
|
} else {
|
|
SCWrite(pCon, "ERROR: not enough arguments to list match", eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "exists") == 0) {
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: not enough arguments", eError);
|
|
return 0;
|
|
} else {
|
|
pCom = FindCommand(pSics, argv[2]);
|
|
if (pCom == NULL) {
|
|
SCWrite(pCon, "ERROR: Object doesn't exist", eError);
|
|
return 0;
|
|
} else
|
|
return existsObjectData(pCon, (pDummy) pCom->pData, argv[3]);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* object properties
|
|
*/
|
|
pCom = FindCommand(pSics, argv[1]);
|
|
if (pCom != NULL) {
|
|
if (argc < 3) {
|
|
listAllObjectData(pCon, argv[1], (pDummy) pCom->pData);
|
|
return 1;
|
|
} else {
|
|
return printObjectData(pCon, (pDummy) pCom->pData, argv[2]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* attribute setting and status
|
|
*/
|
|
if (strcmp(argv[1], "setatt") == 0) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments to setatt",
|
|
eError);
|
|
return 0;
|
|
}
|
|
return setAttribute(pCon, pSics, argv[2], argv[3], argv[4]);
|
|
}
|
|
|
|
/*
|
|
* classes and class membership
|
|
*/
|
|
if (argc < 3) {
|
|
printKeyTypes(pSics, pCon, argv[1]);
|
|
return 1;
|
|
} else {
|
|
printObjectsMatchingKeyVal(pSics, pCon, argv[1], argv[2]);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|