/* A module for displaying various bits of information about SICS internals and objects. copyright: see file COPYRIGHT Mark Koennecke, January 2006 */ #include #include #include #include #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; }