PSI sics-cvs-psi-2006
This commit is contained in:
188
macro.c
188
macro.c
@@ -1,8 +1,8 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
All you need to evaluate macros with SICS.
|
||||
All you need to evaluate macros with SICS
|
||||
|
||||
The implmentation fo the macro stuff is complex and non intuitive.
|
||||
The implmentation for the macro stuff is complex and non intuitive.
|
||||
This is the price to pay for adding the extremly powerful and
|
||||
strong Tcl-interpreter to SICS. The problem is that Tcl does not
|
||||
know anything about connections and our error handling. We have
|
||||
@@ -22,6 +22,8 @@
|
||||
Mark Koennecke, December 1999
|
||||
InternalFileEval added
|
||||
|
||||
Mark Koennecke, May 2004
|
||||
Added protected exec called sys.
|
||||
|
||||
Copyright:
|
||||
|
||||
@@ -68,6 +70,7 @@
|
||||
#include "ifile.h"
|
||||
#include "Dbg.h"
|
||||
#include "servlog.h"
|
||||
#include "stringdict.h"
|
||||
|
||||
#define SICSERROR "005567SICS"
|
||||
/*----------------------------------------------------------------------------
|
||||
@@ -126,7 +129,7 @@
|
||||
SConnection *pCon = NULL;
|
||||
CommandList *pCommand = NULL;
|
||||
char *lastCommand = NULL, comBuffer[132];
|
||||
int iRet,i;
|
||||
int iRet = 0,i;
|
||||
int iMacro;
|
||||
|
||||
/* get the datastructures */
|
||||
@@ -135,6 +138,7 @@
|
||||
pSinter = pSics->pInter;
|
||||
pCon = pSics->pCon[pSics->iStack];
|
||||
lastCommand = pSics->lastUnknown[pSics->iStack];
|
||||
pCon->sicsError = 0;
|
||||
|
||||
assert(pSinter);
|
||||
assert(pCon);
|
||||
@@ -163,21 +167,21 @@
|
||||
{
|
||||
if(strcmp(lastCommand,comBuffer) == 0)
|
||||
{
|
||||
Tcl_AppendResult(pInter,"ERROR: Never ending loop in unknown\n",
|
||||
Tcl_AppendResult(pInter,"ERROR: Never ending loop in unknown\n",
|
||||
"Offending command: ",comBuffer,
|
||||
"Probably Tcl command not found",NULL);
|
||||
" Probably Tcl command not found",NULL);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
pSics->lastUnknown[pSics->iStack] = strdup(comBuffer);
|
||||
if (pSics->lastUnknown[pSics->iStack]) free(pSics->lastUnknown[pSics->iStack]);
|
||||
pSics->lastUnknown[pSics->iStack] = strdup(comBuffer);
|
||||
|
||||
/* invoke */
|
||||
iMacro = SCinMacro(pCon);
|
||||
SCsetMacro(pCon,1);
|
||||
iRet = pCommand->OFunc(pCon,pSinter,pCommand->pData,margc, myarg);
|
||||
SCsetMacro(pCon,iMacro);
|
||||
|
||||
/*
|
||||
lastUnkown gets deeply stacked with each SICS command exec'd.
|
||||
This is not reflected in code. However, lastUnknown has already
|
||||
@@ -190,13 +194,14 @@
|
||||
}
|
||||
|
||||
/* finish */
|
||||
if(iRet)
|
||||
if(iRet == 1)
|
||||
{
|
||||
return TCL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tcl_SetVar(pInter,SICSERROR,"yes",TCL_GLOBAL_ONLY);
|
||||
pCon->sicsError = 1;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -213,6 +218,84 @@
|
||||
free(pData);
|
||||
pUnbekannt = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void KillSicsUnknown(void) {
|
||||
if (pUnbekannt) {
|
||||
UnknownKill(pUnbekannt);
|
||||
pUnbekannt = NULL;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
Implementation of a protected exec command
|
||||
--------------------------------------------------------------------------*/
|
||||
static pStringDict allowedCommands = NULL;
|
||||
/*----------------------------------------------------------------------*/
|
||||
int AllowExec(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: not enough arguments to allowexec",eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usInternal))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(allowedCommands == NULL)
|
||||
{
|
||||
allowedCommands = CreateStringDict();
|
||||
if(allowedCommands == NULL)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: not enough memory for list of allowed system commands",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
StringDictAddPair(allowedCommands,argv[1],"Allowed!");
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void KillExec(ClientData data)
|
||||
{
|
||||
if(allowedCommands != NULL)
|
||||
{
|
||||
DeleteStringDict(allowedCommands);
|
||||
allowedCommands = NULL;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
This is in the Tcl sources
|
||||
*/
|
||||
extern int Tcl_ExecObjCmd(ClientData data, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *CONST objv[]);
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *test = NULL;
|
||||
|
||||
if(objc < 2)
|
||||
{
|
||||
return Tcl_ExecObjCmd(clientData,interp,objc, objv);
|
||||
}
|
||||
|
||||
test = Tcl_GetStringFromObj(objv[1],NULL);
|
||||
if(allowedCommands != NULL)
|
||||
{
|
||||
if(StringDictExists(allowedCommands,test))
|
||||
{
|
||||
return Tcl_ExecObjCmd(clientData,interp,objc, objv);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if we are here, we are not allowed to invoke this command
|
||||
*/
|
||||
Tcl_AppendResult(interp,"System command NOT allowed!",NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
initialises a Tcl-Interpreter, installs SICS unknown mechanism and kills
|
||||
a few dangerous commands from the normal Tcl command set
|
||||
@@ -244,15 +327,22 @@
|
||||
pUnknown->iStack = 0;
|
||||
pUnknown->pInter = pSics;
|
||||
pUnbekannt = pUnknown;
|
||||
Tcl_CreateCommand(pInter,"unknown",SicsUnknownProc,
|
||||
/* the cast before SicsUnknwonProc is to avoid a warning
|
||||
Tcl_CmdProc has a const char instead of char as argument M.Z. */
|
||||
Tcl_CreateCommand(pInter,"unknown",(Tcl_CmdProc *)SicsUnknownProc,
|
||||
pUnknown, UnknownKill);
|
||||
|
||||
|
||||
/* delete dangers */
|
||||
Tcl_DeleteCommand(pInter,"exit");
|
||||
Tcl_DeleteCommand(pInter,"socket");
|
||||
Tcl_DeleteCommand(pInter,"vwait");
|
||||
Tcl_DeleteCommand(pInter,"exec");
|
||||
|
||||
/*
|
||||
install protected exec command
|
||||
*/
|
||||
Tcl_CreateObjCommand(pInter,"exec",ProtectedExec,NULL,KillExec);
|
||||
|
||||
return pInter;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -377,7 +467,6 @@
|
||||
{
|
||||
sprintf(pBueffel," Failed to open file -> %s <- ",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
/* SCSetInterrupt(pCon,eAbortBatch); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -435,7 +524,11 @@
|
||||
{ /* Tcl error */
|
||||
if(strlen(pTcl->result) > 2)
|
||||
{
|
||||
SCWrite(pCon,pTcl->result,eError);
|
||||
/*
|
||||
local copy in order to resolve a valgrind error
|
||||
*/
|
||||
strncpy(pBueffel,pTcl->result,511);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
pCom = Tcl_DStringValue(&command);
|
||||
SCWrite(pCon,"ERROR: in Tcl block:",eError);
|
||||
@@ -453,7 +546,7 @@
|
||||
fclose(fp);
|
||||
Tcl_DStringFree(&command);
|
||||
SCWrite(pCon,"ERROR: batch processing interrupted",eError);
|
||||
SetStatus(eOld);
|
||||
SetStatus(eEager);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -549,7 +642,7 @@
|
||||
int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
OutCode eOut = eStatus;
|
||||
OutCode eOut = eWarning;
|
||||
int i = 0, iCode, iLen;
|
||||
int iMacro;
|
||||
char *ppCode;
|
||||
@@ -614,10 +707,19 @@
|
||||
eOut = eWarning;
|
||||
break;
|
||||
case 7:
|
||||
eOut = eFinish;
|
||||
break;
|
||||
case 8:
|
||||
eOut = eEvent;
|
||||
break;
|
||||
case 9:
|
||||
eOut = eWarning;
|
||||
break;
|
||||
case 10:
|
||||
eOut = eError;
|
||||
break;
|
||||
default:
|
||||
eOut = eStatus;
|
||||
eOut = eWarning;
|
||||
iCode = argc;
|
||||
break;
|
||||
}
|
||||
@@ -742,8 +844,9 @@
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pBueffel[1024];
|
||||
char *pCommand;
|
||||
pPubTcl self = NULL;
|
||||
int iRet;
|
||||
int iRet, length;
|
||||
char *pPtr;
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
|
||||
@@ -762,28 +865,32 @@
|
||||
}
|
||||
|
||||
/* make a string */
|
||||
Arg2Text(argc,argv,pBueffel,1023);
|
||||
|
||||
|
||||
iRet = Tcl_Eval(pTcl,pBueffel);
|
||||
pCommand = Arg2Tcl(argc,argv,pBueffel,sizeof(pBueffel));
|
||||
if (!pCommand) {
|
||||
SCWrite(pCon, "ERROR: no more memory", eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_Eval(pTcl,pCommand);
|
||||
if (pCommand != pBueffel) free(pCommand);
|
||||
if(iRet == TCL_OK)
|
||||
{ /* possibly a bug here */
|
||||
SCWrite(pCon,pTcl->result,eStatus);
|
||||
{
|
||||
/* we do not now why, but at some time it was found that
|
||||
we need a copy, and can not use pTcl->result directly
|
||||
|
||||
SCWrite(pCon,pTcl->result,eStatus);
|
||||
|
||||
let us use SCPrintf, which maked always a copy
|
||||
*/
|
||||
SCPrintf(pCon, eStatus, "%s", pTcl->result);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) == NULL)
|
||||
{
|
||||
pPtr = strdup(pTcl->result);
|
||||
SCWrite(pCon,pPtr,eError);
|
||||
free(pPtr);
|
||||
}
|
||||
else
|
||||
if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) != NULL)
|
||||
{
|
||||
Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY);
|
||||
SCWrite(pCon,pTcl->result,eError);
|
||||
}
|
||||
SCPrintf(pCon,eError,"%s",pTcl->result);
|
||||
return 0;
|
||||
}
|
||||
return 1; /* not reached */
|
||||
@@ -835,6 +942,13 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if the macro already exists */
|
||||
pNew = FindCommandData(pSics, argv[1], "Macro");
|
||||
if (pNew)
|
||||
{ /* yes -> overwrite access code */
|
||||
pNew->iUser = iUser;
|
||||
return 0;
|
||||
}
|
||||
/* do a job !*/
|
||||
pNew = CreatePublish(argv[1],iUser);
|
||||
if(!pNew)
|
||||
@@ -864,17 +978,21 @@
|
||||
int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pCommand[1024], pStart[1024];
|
||||
char pBuffer[1024];
|
||||
char *pCommand;
|
||||
int iRet;
|
||||
|
||||
Arg2Text(argc-1,&argv[1],pCommand,1023);
|
||||
pCommand = Arg2Tcl(argc-1,&argv[1],pBuffer, sizeof(pBuffer));
|
||||
if (!pCommand) {
|
||||
SCWrite(pCon,"ERROR: no memory", eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[0]);
|
||||
if(strcmp(argv[0],"fulltransact") == 0){
|
||||
snprintf(pStart,1024,"TRANSACTIONSTART %s",pCommand);
|
||||
SCWrite(pCon,pStart,eError);
|
||||
SCPrintf(pCon,eError, "TRANSACTIONSTART %s",pCommand);
|
||||
}
|
||||
iRet = InterpExecute(pSics,pCon,pCommand);
|
||||
SicsWait(1);
|
||||
if (pCommand != pBuffer) free(pCommand);
|
||||
SCWrite(pCon,"TRANSACTIONFINISHED",eError);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user