/* 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; } } 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; }