533 lines
16 KiB
C
533 lines
16 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;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------
|
|
* 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;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|