1151 lines
34 KiB
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';
|
|
}
|