Files
sics/sinfox.c

1151 lines
34 KiB
C

/*--------------------------------------------------------------------------
ANSTO Server Info Command Object
Paul Hathaway, January, 2005
Copyright: See copyright.txt
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <conman.h>
#include <obdes.h>
#include <ctype.h>
#include <sics.h>
#include <sicsvar.h>
#include <conman.h> /* incl. SCWrite */
#include <fupa.h>
#include <splitter.h>
#include <outcode.c>
#include <protocol.h>
#include "sinfox.h"
/*-----------------------------------------------------------------------
* External Interface defined in sinfox.h includes
* struct pSinfox
* int InstallSinfox(SConnection *pCon, SicsInterp *pSics, void *pData,
* int argc, char *argv[]);
* void DeleteSinfox(void *pSelf);
* int SinfoxAction(SConnection *pCon, SicsInterp *pSics, void *pData,
* int argc, char *argv[]);
* and lists of option keys
*-----------------------------------------------------------------------*/
/* Core module functions */
static pSinfox CreateSinfox(void);
static int SinfoxInit(SicsInterp * pSics, char *infofile);
static int SinfoxHelp(pSinfox pSin, SicsInterp * pSics);
static int SinfoxReset(pSinfox pSin, SicsInterp * pSics);
static int SinfoxSetDesc(pSinfox pSin, SicsInterp * pSics,
char *objName, char *pDesc);
static int SinfoxSetGrp(pSinfox pSin, SicsInterp * pSics,
char *objName, char *pGrp);
static int SinfoxSetKey(pSinfox pSin, SicsInterp * pSics,
char *objName, char *keyName, char *eltValue);
static int SinfoxReadKey(pSinfox pSin, SicsInterp * pSics,
char *objName, char *fileName);
static int SinfoxList(pSinfox pSin, SicsInterp * pSics, SConnection * pCon,
char *pObjName, char *pKeyName, char *pEltName);
static int SinfoxEnumerate(pSinfox pSin, SicsInterp * pSics,
SConnection * pCon, char *keyName);
static int SinfoxShow(pSinfox pSin, SicsInterp * pSics, SConnection * pCon,
char *keyName, char *eltName);
static int SinfoxDevice(pSinfox pSin, SicsInterp * pSics,
SConnection * pCon, char *devName, char *keyName,
char *eltName);
static int SinfoxGetGrp(pSinfox pSin, SicsInterp * pSics, char *objName);
/* Utility functions */
static int EnumChoice(char *pList[], int iLength, char *pInput);
static int LinkVar(char *tcl_var_name, char *pAddress, int link_flags);
static void setOKE(char *obj, char *key, char *elt,
char *oVal, char *kVal, char *eVal);
static int isNameDevice(char *name);
static int isNameCommand(char *name);
static int isObjectDevice(CommandList * pObj);
static int isObjectCommand(CommandList * pObj);
static void addToList(Tcl_Interp * tTcl, Tcl_Obj * tList, char *prefix,
char *sVal);
static void addPairsToList(Tcl_Interp * tTcl, Tcl_Obj * tList,
IPair * pList);
static void RemoveWhiteSpace(char *pText);
/*--------------------------------------------------------------------------*/
pSinfox CreateSinfox(void)
{
int i;
pSinfox pNew = NULL;
SicsInterp *pSics;
Tcl_Interp *tTcl;
pNew = (pSinfox) malloc(sizeof(Sinfox));
if (!pNew) {
return NULL;
}
pNew->pDes = CreateDescriptor("sinfox");
if (!pNew->pDes) {
free(pNew);
return NULL;
}
pSics = GetInterpreter();
tTcl = (Tcl_Interp *) (pSics->pTcl);
pNew->tTcl = tTcl;
/* LinkVar("server::configName",pNew->configName,TCL_LINK_STRING); */
pNew->buildVersion = Tcl_GetVar(tTcl,
"::server::buildVersion",
TCL_GLOBAL_ONLY);
pNew->configName =
Tcl_GetVar(tTcl, "::server::configName", TCL_GLOBAL_ONLY);
pNew->configVersion =
Tcl_GetVar(tTcl, "::server::configVersion", TCL_GLOBAL_ONLY);
pNew->description =
Tcl_GetVar(tTcl, "::server::description", TCL_GLOBAL_ONLY);
pNew->instrument =
Tcl_GetVar(tTcl, "::server::instrument", TCL_GLOBAL_ONLY);
pNew->schemaVersion =
Tcl_GetVar(tTcl, "::server::schemaVersion", TCL_GLOBAL_ONLY);
pNew->pDes->pKeys = NULL;
return pNew;
}
/*-------------------------------------------------------------------------*/
void DeleteSinfox(void *self)
{
int i;
pSinfox pOld = (pSinfox) self;
if (NULL == pOld) {
return;
}
if (pOld->buildVersion) {
free((void *) (pOld->buildVersion));
}
if (pOld->configName) {
free((void *) (pOld->configName));
}
if (pOld->configVersion) {
free((void *) (pOld->configVersion));
}
if (pOld->description) {
free((void *) (pOld->description));
}
if (pOld->instrument) {
free((void *) (pOld->instrument));
}
if (pOld->schemaVersion) {
free((void *) (pOld->schemaVersion));
}
if (pOld->pDes) {
DeleteDescriptor(pOld->pDes);
}
free(pOld);
}
/*--------------------------------------------------------------------------*/
int InstallSinfox(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pSinfox pNew = NULL;
pNew = CreateSinfox();
if (NULL == pNew) {
SCWrite(pCon, "No memory to create Sinfox", eError);
return 0;
}
AddCommand(pSics, "sinfox", SinfoxAction, DeleteSinfox, pNew);
SCSendOK(pCon);
return 1;
}
/*--------------------------------------------------------------------------*/
static int SinfoxInit(SicsInterp * pSics, char *infofile)
{
SConnection *pCon = NULL;
char pBuf[1024];
int iRet;
/* create a connection */
pCon = SCCreateDummyConnection(pSics);
if (!pCon) {
return 0;
}
/*
pCon->iFiles = 1;
pCon->pFiles[0] = stdout;
*/
/* evaluate the file */
sprintf(pBuf, "fileeval %s", infofile);
iRet = InterpExecute(pSics, pCon, pBuf);
/*
pCon->iFiles = 0;
*/
SCDeleteConnection(pCon);
return iRet;
}
/*------------------------------------------------------------------------*/
static int SinfoxHelp(pSinfox pSin, SicsInterp * pSics)
{
Tcl_SetResult((Tcl_Interp *) (pSics->pTcl), "Sinfox Help", TCL_VOLATILE);
return 1;
}
/*------------------------------------------------------------------------*/
static int SinfoxReset(pSinfox pSin, SicsInterp * pSics)
{
int i;
pSin->buildVersion = Tcl_GetVar(pSin->tTcl,
"::server::buildVersion",
TCL_GLOBAL_ONLY);
pSin->configName =
Tcl_GetVar(pSin->tTcl, "::server::configName", TCL_GLOBAL_ONLY);
pSin->configVersion =
Tcl_GetVar(pSin->tTcl, "::server::configVersion", TCL_GLOBAL_ONLY);
pSin->description =
Tcl_GetVar(pSin->tTcl, "::server::description", TCL_GLOBAL_ONLY);
pSin->instrument =
Tcl_GetVar(pSin->tTcl, "::server::instrument", TCL_GLOBAL_ONLY);
pSin->schemaVersion =
Tcl_GetVar(pSin->tTcl, "::server::schemaVersion", TCL_GLOBAL_ONLY);
Tcl_SetResult(pSin->tTcl, "{Sinfox Reset}", TCL_VOLATILE);
return 1;
}
/*------------------------------------------------------------------------*/
static int SinfoxSetDesc(pSinfox pSin, SicsInterp * pSics,
char *objName, char *pDesc)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
char pBuf[256];
memset(pBuf, 0, 256);
pCurrent = pSics->pCList;
pCurrent = FindCommand(pSics, objName);
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
SetDescriptorDescription(pDes, pDesc);
sprintf(pBuf, "description=%s", pDesc);
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 1;
}
}
sprintf(pBuf, "error=unable to set %s.description to %s", objName,
pDesc);
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 0;
}
/*------------------------------------------------------------------------*/
static int SinfoxSetGrp(pSinfox pSin, SicsInterp * pSics,
char *objName, char *pGrp)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
char pBuf[256];
memset(pBuf, 0, 256);
pCurrent = pSics->pCList;
pCurrent = FindCommand(pSics, objName);
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
SetDescriptorGroup(pDes, pGrp);
sprintf(pBuf, "group=%s", pGrp);
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 1;
}
}
sprintf(pBuf, "error=unable to set %s.group to %s", objName, pGrp);
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 0;
}
static int SinfoxGetGrp(pSinfox pSin, SicsInterp * pSics, char *objName)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
char pBuf[256];
pBuf[0] = '\0';
pCurrent = pSics->pCList;
pCurrent = FindCommand(pSics, objName);
if (NULL == pCurrent) {
sprintf(pBuf, "%s.group=none", objName);
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 1;
} else {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
sprintf(pBuf, "%s.group=%s", objName, GetDescriptorGroup(pDes));
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return 1;
}
}
return 0;
}
/*------------------------------------------------------------------------*/
static int SinfoxSetKey(pSinfox pSin, SicsInterp * pSics,
char *objName, char *keyName, char *eltValue)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
int bOK = 0;
char *obj;
char pBuf[256];
memset(pBuf, 0, 256);
obj = strdup(objName);
strtolower(obj);
if (0 == strcmp(obj, "server")) { /* sinfox object is surrogate for server object inside SICS */
free(obj);
obj = strdup("sinfox");
} else {
free(obj);
obj = strdup(objName);
}
pCurrent = pSics->pCList;
pCurrent = FindCommand(pSics, obj);
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
strtolower(keyName);
strtolower(eltValue);
pDes->pKeys = IFSetOption(pDes->pKeys, keyName, eltValue);
if (NULL != pDes->pKeys) {
bOK = 1;
}
}
}
if (bOK == 1) {
sprintf(pBuf, "%s.%s=%s",
pCurrent->pName, pDes->pKeys->name, pDes->pKeys->value);
} else {
sprintf(pBuf, "error=unable to set %s.%s to %s",
obj, keyName, eltValue);
}
Tcl_SetObjResult(pSin->tTcl, Tcl_NewStringObj(pBuf, strlen(pBuf)));
return bOK;
}
/*------------------------------------------------------------------------*/
static int SinfoxReadKey(pSinfox pSin, SicsInterp * pSics,
char *objName, char *fileName)
{
static FILE *fKeyFile = NULL;
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
char pBuf[256];
char pName[132];
char pValue[132];
char *pPos;
int iLen;
memset(pBuf, 0, 256);
pCurrent = pSics->pCList;
pCurrent = FindCommand(pSics, objName);
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
fKeyFile = fopen(fileName, "r");
if (NULL == fKeyFile) {
return 0;
}
while (!feof(fKeyFile)) {
fgets(pBuf, 255, fKeyFile);
if (feof(fKeyFile))
continue;
if (pBuf[0] == '#')
continue;
pPos = strchr(pBuf, '=');
if (!pPos)
continue;
iLen = pPos - pBuf;
strncpy(pName, pBuf, iLen); /* strlcpy is wrong here */
pName[iLen] = '\0';
strcpy(pValue, (pPos + 1));
RemoveWhiteSpace(pName);
RemoveWhiteSpace(pValue);
strtolower(pName);
strtolower(pValue);
pDes->pKeys = IFAddOption(pDes->pKeys, pName, pValue);
if (NULL == pDes->pKeys)
return 0;
}
fclose(fKeyFile);
return 1;
}
}
return 0;
}
/*------------------------------------------------------------------------*/
static int SinfoxList(pSinfox pSin, SicsInterp * pSics, SConnection * pCon,
char *pObjName, char *pKeyName, char *pEltName)
{
int iRet;
char *objName;
char *keyName = NULL;
char *eltName = NULL;
CommandList *pObj = NULL;
objName = strdup(pObjName);
strtolower(objName);
if (NULL != pKeyName) {
keyName = strdup(pKeyName);
strtolower(keyName);
}
if (NULL != pEltName) {
eltName = strdup(pEltName);
strtolower(eltName);
}
/* check if objName is an interfaceName */
iRet = EnumChoice(pIFaces, iNumIFaces, objName);
if (-1 < iRet) {
if ((0 == strcmp(keyName, "device")) || keyName == NULL) { /* format as sinfox list server interface interfaceName */
setOKE(objName, keyName, eltName, "server", "interface", objName);
} else if (0 == strcmp(keyName, "command")) { /* todo: not yet implemented */
return SinfoxHelp(pSin, pSics);
}
}
/* check if objName is commandName */
/* check if objName is a deviceName */
pObj = FindCommand(pSics, objName);
if (NULL != pObj) {
if (1 == isObjectDevice(pObj)) {
return SinfoxDevice(pSin, pSics, pCon, objName, keyName, eltName);
} else { /* command */
return 0;
iRet = EnumChoice(pCommandKeys, iNumCommandKeys, keyName);
switch (iRet) {
case 1: /* argument */
/* todo: not yet implemented */
case 2: /* device */
/* todo: secondary: not yet implemented */
case 3: /* interface */
/* todo: secondary: not yet implemented */
default: /* sinfox list server command commandName */
setOKE(objName, keyName, eltName, "server", "command", objName);
break;
}
}
}
if (0 == strcmp(objName, "server")) {
iRet = EnumChoice(pServerKeys, iNumServerKeys, keyName);
/* if invalid (iRet < 0) then default to "help" command */
switch (iRet) {
/* cases that have no eltName argument */
case 1: /* list */
case 3: /* connection */
case 6: /* experiment */
case 9: /* key */
return SinfoxEnumerate(pSin, pSics, pCon, keyName);
break;
/* cases that are not fully implemented */
case 2: /* command */
case 4: /* device */
case 5: /* deviceType */
case 7: /* group */
case 8: /* interface */
return SinfoxShow(pSin, pSics, pCon, keyName, eltName);
break;
/* fully functional cases */
case 0: /* help */
default:
return SinfoxHelp(pSin, pSics);
break;
}
return 1;
}
return 0;
}
/*------------------------------------------------------------------------*/
/* Retrieve a list of elements from CommandList matching criteria */
static int SinfoxEnumerate(pSinfox pSin, SicsInterp * pSics,
SConnection * pCon, char *keyName)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
Tcl_Interp *tTcl;
Tcl_Obj *tList;
IPair *pOption = NULL;
IPair *pGroups = NULL;
pSicsVariable pSVar = NULL;
int iRet;
char pBuf[256], *pPtr = NULL;
int checkDeviceTypes[iNumDeviceTypes];
pCurrent = pSics->pCList;
tTcl = (Tcl_Interp *) (pSics->pTcl);
tList = Tcl_NewListObj(0, NULL);
memset(pBuf, 0, 256);
iRet = EnumChoice(pServerKeys, iNumServerKeys, keyName);
/* if invalid (iRet < 0) then default to "help" command */
switch (iRet) {
/* cases that have no eltName argument - not fully implemented */
case 1: /* list */
addToList(tTcl, tList, "buildVersion", (char *) (pSin->buildVersion));
addToList(tTcl, tList, "configName", (char *) (pSin->configName));
addToList(tTcl, tList, "configVersion",
(char *) (pSin->configVersion));
addToList(tTcl, tList, "description", (char *) (pSin->description));
addToList(tTcl, tList, "instrument", (char *) (pSin->instrument));
addToList(tTcl, tList, "schemaVersion",
(char *) (pSin->schemaVersion));
addPairsToList(tTcl, tList, pSin->pDes->pKeys);
addPairsToList(tTcl, tList, pSICSOptions);
break;
case 2: /* command */
while (pCurrent) {
if (1 == isObjectCommand(pCurrent)) {
strcpy(pBuf, pCurrent->pName);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
pCurrent = pCurrent->pNext;
}
break;
case 3: /* connection */
sprintf(pBuf, "%d", SCGetRights(pCon));
addToList(tTcl, tList, "userAccessLevel", pBuf);
addToList(tTcl, tList, "protocol", GetProtocolName(pCon));
break;
case 6: /* experiment */
while (pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
strcpy(pBuf, pDes->name);
strtolower(pBuf);
if (0 == strcmp(pBuf, "sicsvariable")) {
pSVar = FindVariable(pSics, pCurrent->pName);
addToList(tTcl, tList, pCurrent->pName, pSVar->text);
}
}
pCurrent = pCurrent->pNext;
}
break;
case 9: /* key */
for (iRet = 0; iRet < iNumServerKeys; iRet++) {
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pServerKeys[iRet],
strlen(pServerKeys
[iRet])));
}
break;
/* cases that have not specified eltName */
case 4: /* device */
while (pCurrent) {
if (1 == isObjectDevice(pCurrent)) {
strcpy(pBuf, pCurrent->pName);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
pCurrent = pCurrent->pNext;
}
break;
case 5: /* deviceType */
for (iRet = 0; iRet < iNumDeviceTypes; iRet++) {
checkDeviceTypes[iRet] = 0;
}
while (pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
strcpy(pBuf, pDes->name);
strtolower(pBuf);
iRet = EnumChoice(pDeviceTypes, iNumDeviceTypes, pBuf);
if (-1 < iRet) {
if (1 != checkDeviceTypes[iRet]) {
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
checkDeviceTypes[iRet] = 1;
}
}
}
pCurrent = pCurrent->pNext;
}
break;
case 7: /* group */
pCurrent = pSics->pCList;
/* Always add default group "none" */
pGroups = IFAddOption(pGroups, "none", "OK");
Tcl_ListObjAppendElement(tTcl, tList, Tcl_NewStringObj("none", 4));
while (pCurrent) {
if (1 == isObjectDevice(pCurrent)) {
pDes = FindDescriptor(pCurrent->pData);
if ((pPtr = IFindOption(pDes->pKeys, "group")) != NULL) {
strcpy(pBuf, pPtr);
strtolower(pBuf);
if (NULL == IFindOption(pGroups, pBuf)) {
pGroups = IFAddOption(pGroups, pBuf, "OK");
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
}
pCurrent = pCurrent->pNext;
}
if (NULL != pGroups) {
IFDeleteOptions(pGroups);
}
break;
case 8: /* interface */
for (iRet = 0; iRet < iNumIFaces; iRet++) {
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pIFaces[iRet],
strlen(pIFaces[iRet])));
}
break;
/* special cases */
case 0: /* help */
default:
return SinfoxHelp(pSin, pSics);
break;
}
Tcl_SetObjResult(tTcl, tList);
return 1;
}
/*------------------------------------------------------------------------*/
static int SinfoxShow(pSinfox pSin, SicsInterp * pSics, SConnection * pCon,
char *keyName, char *eltName)
{
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
Tcl_Interp *tTcl;
Tcl_Obj *tList;
int iRet, iType;
char pBuf[256];
char *pTmp;
char *pElt;
pCurrent = pSics->pCList;
tTcl = (Tcl_Interp *) (pSics->pTcl);
tList = Tcl_NewListObj(0, NULL);
memset(pBuf, 0, 256);
if (NULL == eltName) {
return SinfoxEnumerate(pSin, pSics, pCon, keyName);
}
pElt = strdup(eltName);
strtolower(pElt);
iRet = EnumChoice(pServerKeys, iNumServerKeys, keyName);
/* if invalid (iRet < 0) then default to "help" command */
switch (iRet) {
case 2: /* command */
case 4: /* device - list deviceName {attribute|command|interface} */
//addToList(tTcl,tList,pElt,"is being searched for");
pCurrent = FindCommand(pSics, pElt);
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
//addToList(tTcl,tList,"debug2","descriptor found");
if (1 == isObjectDevice(pCurrent)) {
if (NULL != pDes->name) {
strcpy(pBuf, pDes->name);
strtolower(pBuf);
addToList(tTcl, tList, "devicetype", pBuf);
}
if ((pTmp = IFindOption(pDes->pKeys, "group")) != NULL) {
strcpy(pBuf, pTmp);
strtolower(pBuf);
addToList(tTcl, tList, "group", pBuf);
}
}
if ((pTmp = IFindOption(pDes->pKeys, "description")) != NULL) {
strcpy(pBuf, pTmp);
strtolower(pBuf);
addToList(tTcl, tList, "description", pBuf);
}
//addToList(tTcl,tList,"debug3","default fields processed");
if (NULL != pDes->pKeys) {
addPairsToList(tTcl, tList, pDes->pKeys);
}
}
}
//addToList(tTcl,tList,"debug4","device show finished");
break;
case 5: /* devicetype */
iRet = EnumChoice(pDeviceTypes, iNumDeviceTypes, pElt);
if (0 > iRet) {
if ((0 == strcmp(pElt, "all")) || (0 == strcmp(pElt, "*"))) {
Tcl_SetVar(tTcl, "name", keyName, 0);
return SinfoxEnumerate(pSin, pSics, pCon, keyName);
}
} else {
while (pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
strcpy(pBuf, pDes->name);
strtolower(pBuf);
if (0 == strcmp(pElt, pBuf)) {
strcpy(pBuf, pCurrent->pName);
strtolower(pBuf);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
pCurrent = pCurrent->pNext;
}
}
break;
case 7: /* group */
if ((0 == strcmp(pElt, "all")) || (0 == strcmp(pElt, "*"))) {
Tcl_SetVar(tTcl, "name", keyName, 0);
return SinfoxEnumerate(pSin, pSics, pCon, keyName);
}
while (NULL != pCurrent) {
if (1 == isObjectDevice(pCurrent)) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
if ((pTmp = IFindOption(pDes->pKeys, "group")) == NULL) {
strcpy(pBuf, "none");
} else {
strcpy(pBuf, pTmp);
strtolower(pBuf);
}
if (0 == strcmp(pElt, pBuf)) {
strcpy(pBuf, pCurrent->pName);
strtolower(pBuf);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
}
pCurrent = pCurrent->pNext;
}
break;
case 8: /* interface */
iRet = EnumChoice(pIFaces, iNumIFaces, pElt);
if (0 > iRet) {
if ((0 == strcmp(pElt, "all")) || (0 == strcmp(pElt, "*"))) {
Tcl_SetVar(tTcl, "name", keyName, 0);
return SinfoxEnumerate(pSin, pSics, pCon, keyName);
}
} else {
switch (iRet) {
case 0: /* callback */
iType = CALLBACKINTERFACE;
break;
case 1: /* countable */
iType = COUNTID;
break;
case 2: /* drivable */
iType = DRIVEID;
break;
case 3: /* environment */
iType = ENVIRINTERFACE;
break;
default: /* interface not recognised */
Tcl_SetObjResult(tTcl, tList);
return 1;
break;
}
while (pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
if (NULL != pDes->GetInterface(pDes, iType)) {
strcpy(pBuf, pCurrent->pName);
strtolower(pBuf);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
pCurrent = pCurrent->pNext;
}
}
break;
default:
addToList(tTcl, tList, "error", "unknown key");
break;
}
Tcl_SetObjResult(tTcl, tList);
return 1;
}
/*-------------------------------------------------------------------------*/
static int SinfoxDevice(pSinfox pSin, SicsInterp * pSics,
SConnection * pCon, char *devName, char *keyName,
char *eltName)
{
int i, iRet, iType;
Tcl_Obj *tList;
char pBuf[256];
char *pTmp;
CommandList *pCurrent;
pObjectDescriptor pDes = NULL;
memset(pBuf, 0, 256);
pCurrent = pSics->pCList;
tList = Tcl_NewListObj(0, NULL);
pCurrent = FindCommand(pSics, devName);
/* debug */
addToList(pSin->tTcl, tList, "dev", devName);
addToList(pSin->tTcl, tList, "key", keyName);
addToList(pSin->tTcl, tList, "elt", eltName);
/*-------*/
iRet = EnumChoice(pDeviceKeys, iNumDeviceKeys, keyName);
switch (iRet) {
case 2: /* interface */
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
for (i = 0; i < iNumIFaces; i++) {
switch (i) {
case 0: /* callback */
iType = CALLBACKINTERFACE;
break;
case 1: /* countable */
iType = COUNTID;
break;
case 2: /* drivable */
iType = DRIVEID;
break;
case 3: /* environment */
iType = ENVIRINTERFACE;
break;
default: /* interface not recognised */
Tcl_SetObjResult(pSin->tTcl, tList);
return 0;
break;
}
if (NULL != pDes->GetInterface(pDes, iType)) {
strcpy(pBuf, pIFaces[i]);
Tcl_ListObjAppendElement(pSin->tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
}
}
break;
case 0: /* attribute */
if (NULL == eltName) {
return SinfoxShow(pSin, pSics, pCon, "device", devName);
} else {
if (NULL != pCurrent) {
pDes = FindDescriptor(pCurrent->pData);
if (NULL != pDes) {
pTmp = IFindOption(pDes->pKeys, eltName);
if (NULL != pTmp) {
strcpy(pBuf, pTmp);
addToList(pSin->tTcl, tList, eltName, pTmp);
}
}
}
}
break;
case 1: /* command */
/* todo: secondary: not yet implemented */
default: /* sinfox list server device deviceName */
return SinfoxShow(pSin, pSics, pCon, "device", devName);
break;
}
Tcl_SetObjResult(pSin->tTcl, tList);
return 1;
}
/*-------------------------------------------------------------------------*/
int SinfoxAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int iRet;
char **argx;
FuPaResult PaRes;
pSinfox pSin = NULL;
const int iNumCmds = 8;
FuncTemplate CommandTemplate[] = {
{"help", 0, {0, 0}},
{"list", 3, {FUPATEXT, FUPATEXT, FUPAOPT}},
{"setdesc", 2, {FUPATEXT, FUPATEXT}},
{"setgrp", 2, {FUPATEXT, FUPATEXT}},
{"setkey", 3, {FUPATEXT, FUPATEXT, FUPATEXT}},
{"reset", 0, {0, 0}},
{"readkey", 2, {FUPATEXT, FUPATEXT}},
{"getgrp", 1, {FUPATEXT}},
{NULL}
};
assert(pCon);
assert(pSics);
pSin = (pSinfox) pData;
assert(pSin);
/* You need to have User level access rights to use this facility */
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
/* parse function args */
argtolower(argc, argv);
argx = &argv[1];
iRet =
EvaluateFuPa((pFuncTemplate) & CommandTemplate, iNumCmds, argc - 1,
argx, &PaRes);
/* if invalid (iRet < 0) then default to "help" command */
switch (iRet) {
case 1: /* list */
if (1 == PaRes.Arg[2].iVal) {
iRet = SinfoxList(pSin, pSics, pCon,
PaRes.Arg[0].text, PaRes.Arg[1].text,
PaRes.Arg[2].text);
} else {
iRet = SinfoxList(pSin, pSics, pCon,
PaRes.Arg[0].text, PaRes.Arg[1].text, NULL);
}
return iRet;
break;
case 2: /* setdesc */
return SinfoxSetDesc(pSin, pSics,
PaRes.Arg[0].text, PaRes.Arg[1].text);
break;
case 3: /* setgrp */
return SinfoxSetGrp(pSin, pSics, PaRes.Arg[0].text, PaRes.Arg[1].text);
break;
case 4: /* setkey */
return SinfoxSetKey(pSin, pSics,
PaRes.Arg[0].text, PaRes.Arg[1].text,
PaRes.Arg[2].text);
break;
case 5: /* reset */
return SinfoxReset(pSin, pSics);
break;
case 6: /* readkey */
return SinfoxReadKey(pSin, pSics,
PaRes.Arg[0].text, PaRes.Arg[1].text);
break;
case 7: /*getgrp */
return SinfoxGetGrp(pSin, pSics, PaRes.Arg[0].text);
break;
case 0: /* help */
default:
return SinfoxHelp(pSin, pSics);
break;
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int EnumChoice(char *pList[], int iLength, char *pInput)
{
int i;
int iRet = -1;
for (i = 0; i < iLength; i++) {
if (0 == strcmp(pInput, pList[i])) {
iRet = i;
break;
}
}
return iRet;
}
/*-------------------------------------------------------------------------*/
static int LinkVar(char *tcl_var_name, char *pAddress, int link_flags)
{
SicsInterp *pSics = NULL;
Tcl_Interp *pTcl = NULL;
int tcl_flags = TCL_LINK_INT;
pSics = GetInterpreter();
pTcl = (Tcl_Interp *) (pSics->pTcl);
/* tcl_flags = f(link_flags) */
switch (link_flags) {
case TCL_LINK_INT:
break;
case TCL_LINK_DOUBLE:
case TCL_LINK_BOOLEAN:
case TCL_LINK_STRING:
tcl_flags = link_flags;
break;
default:
return 0;
}
Tcl_LinkVar(pTcl, tcl_var_name, pAddress, tcl_flags);
return 1;
}
/*-------------------------------------------------------------------------*/
static void setOKE(char *obj, char *key, char *elt, char *oVal, char *kVal,
char *eVal)
{
char *eBuf;
char *kBuf;
char *oBuf;
eBuf = strdup(eVal);
kBuf = strdup(kVal);
oBuf = strdup(oVal);
free(elt);
elt = eBuf;
free(key);
key = kBuf;
free(obj);
obj = oBuf;
}
/*-------------------------------------------------------------------------*/
static int isNameDevice(char *name)
{
SicsInterp *pSics;
CommandList *pObj = NULL;
Dummy *pDum = NULL;
pSics = GetInterpreter();
pObj = FindCommand(pSics, name);
if (NULL != pObj) {
pDum = (Dummy *) pObj->pData;
if (NULL != pDum) {
if (NULL != pDum->pDescriptor->GetInterface(pDum, DRIVEID))
return 1;
if (NULL != pDum->pDescriptor->GetInterface(pDum, COUNTID))
return 1;
if (NULL != pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE))
return 1;
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int isNameCommand(char *name)
{
SicsInterp *pSics;
CommandList *pObj = NULL;
Dummy *pDum = NULL;
pSics = GetInterpreter();
pObj = FindCommand(pSics, name);
if (NULL != pObj) {
pDum = (Dummy *) pObj->pData;
if (NULL != pDum) {
if (NULL != pDum->pDescriptor->GetInterface(pDum, DRIVEID))
return 0;
if (NULL != pDum->pDescriptor->GetInterface(pDum, COUNTID))
return 0;
if (NULL != pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE))
return 0;
}
return 1;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int isObjectDevice(CommandList * pObj)
{
Dummy *pDum = NULL;
if (NULL != pObj) {
pDum = (Dummy *) pObj->pData;
if (NULL != pDum) {
if (NULL != pDum->pDescriptor->GetInterface(pDum, DRIVEID))
return 1;
if (NULL != pDum->pDescriptor->GetInterface(pDum, COUNTID))
return 1;
if (NULL != pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE))
return 1;
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int isObjectCommand(CommandList * pObj)
{
Dummy *pDum = NULL;
if (NULL != pObj) {
pDum = (Dummy *) pObj->pData;
if (NULL != pDum) {
if (NULL != pDum->pDescriptor->GetInterface(pDum, DRIVEID))
return 0;
if (NULL != pDum->pDescriptor->GetInterface(pDum, COUNTID))
return 0;
if (NULL != pDum->pDescriptor->GetInterface(pDum, ENVIRINTERFACE))
return 0;
}
return 1;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static void addToList(Tcl_Interp * tTcl, Tcl_Obj * tList, char *prefix,
char *sVal)
{
char pBuf[256];
if (NULL != sVal) {
memset(pBuf, 0, 256);
sprintf(pBuf, "%s=%s", prefix, sVal);
Tcl_ListObjAppendElement(tTcl, tList,
Tcl_NewStringObj(pBuf, strlen(pBuf)));
}
}
/*-------------------------------------------------------------------------*/
static void addPairsToList(Tcl_Interp * tTcl, Tcl_Obj * tList,
IPair * pList)
{
IPair *pCurrent;
if (NULL != pList) {
pCurrent = pList;
while (NULL != pCurrent) {
addToList(tTcl, tList, pCurrent->name, pCurrent->value);
pCurrent = pCurrent->pNext;
}
}
}
/*--------------------------------------------------------------------------*/
static void RemoveWhiteSpace(char *pText)
{
int i, ii, i3;
char *pPtr;
if (NULL == pText)
return;
/* find start */
i = 0;
while (isspace(pText[i])) {
i++;
}
/* find end */
ii = strlen(pText);
ii--;
while ((isspace(pText[ii])) || (pText[ii] == '\n')) {
ii--;
}
/* copy it */
pPtr = pText;
for (i3 = i; i3 < (ii + 1); i3++) {
*pPtr = pText[i3];
pPtr++;
}
*pPtr = '\0';
}