Files
sics/conman.c
2000-02-07 10:38:55 +00:00

1428 lines
36 KiB
C

/*--------------------------------------------------------------------------
Connection management for SICS. This is one the core files for
SICS. Does a lot. See the descriptions with individual functions
below.
Mark Koennecke, October 1996
SMInvoke added. Mark Koennecke, April 1997
Seriously revised and extended for new structure with Tasker:
Mark Koennecke, September 1997
Support for writing telnet compatible strings ins SCWrite added.
Mark Koennecke, January 1998
SCWriteBinary added. Mark Koennecke, April 1998
Copyright: see copyright.h
-----------------------------------------------------------------------------*/
#include "fortify.h"
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <tcl.h>
#include "lld.h"
#include "conman.h"
#include "passwd.h"
#include "SCinter.h"
#include "Scommon.h"
#include "splitter.h"
#include "macro.h"
#include "servlog.h"
#include "status.h"
#include "interrupt.h"
#include "interface.h"
#include "event.h"
#include "ifile.h"
#include "token.h"
#include "uubuffer.h"
#include "commandlog.h"
/*
#define UUDEB 1
define UUDEB , for buffer writing for checking encoding */
extern pServer pServ;
/*------ Max Size of Command Stack */
#define MAXSTACK 100
/*---------- Magic ID Header */
#define CONMAGIC 26051958
/*-------------------------------------------------------------------------
a structure for holding callback info
*/
typedef struct {
long lID;
pICallBack pInterface;
} Item;
/*------------- a number for generating automatic names --------------------*/
static int iName = 0;
static int SCNormalWrite(SConnection *self, char *buffer, int iOut);
/*===========================================================================*/
SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser)
{
int i;
SConnection *pRes = NULL;
char pBueffel[253];
char pHost[132];
pRes = (SConnection *)malloc(sizeof(SConnection));
if(!pRes)
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
return NULL;
}
memset(pRes,0,sizeof(SConnection));
/* a descriptor */
pRes->pDes = CreateDescriptor("Connection");
if(!pRes->pDes)
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
free(pRes);
return NULL;
}
/* new name */
sprintf(pBueffel,"CON%4.4d",iName);
iName++;
if(iName > 9999)
{
iName = 0;
}
/* the callback registry */
pRes->iList = LLDcreate(sizeof(Item));
/* the command stack */
pRes->pStack = CreateCommandStack();
if( (pRes->iList <0) || (!pRes->pStack))
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
DeleteDescriptor(pRes->pDes);
free(pRes);
return NULL;
}
SetCommandStackMaxSize(pRes->pStack,MAXSTACK);
pRes->pName = strdup(pBueffel);
pRes->pSock = pSock;
pRes->iUserRights = iUser;
pRes->iOutput = eInError; /* gets everything except internal messages */
pRes->iFiles = 0; /* default: no logfiles */
pRes->inUse = 0;
pRes->iMacro = 0;
pRes->iGrab = TokenGrabActive();
pRes->iTelnet = 0;
pRes->pSics = pSics;
pRes->eInterrupt = eContinue;
pRes->lMagic = CONMAGIC;
pRes->iDummy = 0;
pRes->write = SCNormalWrite;
for(i = 0; i < 10; i++)
{
pRes->pFiles[i] = NULL;
}
if(pRes->pSock)
{
NETInfo(pRes->pSock,pHost,131);
sprintf(pBueffel,"Accepted connection on socket %d from %s",
pRes->pSock->sockid, pHost);
SICSLogWrite(pBueffel,eInternal);
WriteToCommandLog("SYS >", pBueffel);
}
else
{
SICSLogWrite("Accepted dummy connection ",eInternal);
}
/* install command */
AddCommand(pRes->pSics, pRes->pName, ConSicsAction, NULL,pRes);
return pRes;
}
/*--------------------------------------------------------------------------*/
SConnection *SCCreateDummyConnection(SicsInterp *pSics)
{
int i;
SConnection *pRes = NULL;
char pBueffel[132];
pRes = (SConnection *)malloc(sizeof(SConnection));
if(!pRes)
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
return NULL;
}
memset(pRes,0,sizeof(SConnection));
/* a descriptor */
pRes->pDes = CreateDescriptor("Connection");
if(!pRes->pDes)
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
free(pRes);
return NULL;
}
/* new name */
sprintf(pBueffel,"CON%4.4d",iName);
iName++;
if(iName > 9999)
{
iName = 0;
}
/* the callback registry */
pRes->iList = LLDcreate(sizeof(Item));
/* the command stack */
pRes->pStack = CreateCommandStack();
if( (pRes->iList <0) || (!pRes->pStack))
{
/* This is a serious, very serious error! */
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
DeleteDescriptor(pRes->pDes);
free(pRes);
return NULL;
}
pRes->pName = strdup(pBueffel);
pRes->pSock = NULL;
pRes->iUserRights = usInternal;
pRes->iOutput = eInError; /* gets everything except internal messages */
pRes->iFiles = 0; /* default: no logfiles */
pRes->inUse = 0;
pRes->iTelnet = 0;
pRes->iGrab = 0;
pRes->iMacro = 0;
pRes->pSics = pSics;
pRes->lMagic = CONMAGIC;
pRes->eInterrupt = eContinue;
pRes->iDummy = 0;
pRes->write = SCNormalWrite;
for(i = 0; i < 10; i++)
{
pRes->pFiles[i] = NULL;
}
if(pRes->pSock)
{
sprintf(pBueffel,"Accepted connection on socket %d",pRes->pSock->sockid);
SICSLogWrite(pBueffel,eInternal);
}
else
{
SICSLogWrite("Accepted dummy connection ",eInternal);
}
/* install command */
AddCommand(pRes->pSics, pRes->pName, ConSicsAction, NULL,pRes);
return pRes;
}
/*--------------------------------------------------------------------------*/
static int VerifyConnection(SConnection *self)
{
if(!self)
{
SICSLogWrite("MAGICERROR: Invalid call to NULL connection",eError);
return 0;
}
if(self->lMagic != CONMAGIC)
{
SICSLogWrite("MAGICERROR: corrupted connection object",eError);
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
int SCAddLogFile(SConnection *self, char *name)
{
char pBueffel[256];
int iNum, i;
if(!VerifyConnection(self))
{
return 0;
}
/* find an empty number */
if(self->iFiles < MAXLOGFILES)
{
iNum = self->iFiles;
self->iFiles++;
}
else /* scan for an empty slot */
{
iNum = -1;
for(i = 0; i < self->iFiles; i++)
{
if(self->pFiles[i] == NULL)
{
iNum = i;
break;
}
}
}
/* nothing found ? */
if(iNum < 0)
{
SCWrite(self,"ERROR: maximum number of logfiles exhausted",eError);
return -1;
}
/* do the job */
self->pFiles[iNum] = fopen(name,"a+");
if(self->pFiles[iNum] == NULL)
{
sprintf(pBueffel,"ERROR Could not open logfile - %s -",name);
SCWrite(self,pBueffel, 10);
return -1; /* false */
}
else
{
return iNum; /* success */
}
}
/*--------------------------------------------------------------------------*/
int SCDelLogFile(SConnection *self, int iNum)
{
if(!VerifyConnection(self))
{
return 0;
}
if( (iNum >= 0) && (iNum < MAXLOGFILES) )
{
if(self->pFiles[iNum])
{
fclose(self->pFiles[iNum]);
self->pFiles[iNum] = NULL;
return 1;
}
}
return 0;
}
/*----------------------------------------------------------------------------*/
void SCSetOutputClass(SConnection *self, int iClass)
{
if(!VerifyConnection(self))
{
return;
}
self->iOutput = iClass;
}
/*---------------------------------------------------------------------------*/
int SCinMacro(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
if(self->iMacro)
{
return 1;
}
else
{
return 0;
}
}
/*---------------------------------------------------------------------------*/
int SCsetMacro(SConnection *self, int iMode)
{
if(!VerifyConnection(self))
{
return 0;
}
assert( (iMode == 0) || (iMode == 1));
self->iMacro = iMode;
return 1;
}
/*---------------------------------------------------------------------------*/
void SCDeleteConnection(void *pData)
{
int i, iRet;
char pBueffel[132];
SConnection *pVictim = NULL;
Item sItem;
pVictim = (SConnection *)pData;
if(!VerifyConnection(pVictim))
{
return;
}
/* remove the connection from the server log if it has captured
something
*/
KillCapture(pVictim);
/*
If we have a grab, release it !
*/
if(!pVictim->iGrab)
{
if(pServ->pTasker)
{
TaskSignal(pServ->pTasker,TOKENRELEASE,NULL);
TokenRelease();
}
}
/* log the kill */
if(pVictim->pSock)
{
sprintf(pBueffel,"Deleting connection %d",pVictim->pSock->sockid);
WriteToCommandLog("SYS>",pBueffel);
SICSLogWrite(pBueffel,eInternal);
}
/* close all open files and sockets */
if(pVictim->pSock)
{
NETWrite(pVictim->pSock,"SICSCLOSE",sizeof("SICSCLOSE"));
NETClosePort(pVictim->pSock);
free(pVictim->pSock);
}
for(i = 0; i < pVictim->iFiles; i++)
{
fclose(pVictim->pFiles[i]);
}
if(pVictim->pName)
{
RemoveCommand(pVictim->pSics,pVictim->pName);
free(pVictim->pName);
}
if(pVictim->pDes)
{
DeleteDescriptor(pVictim->pDes);
}
/* remove all callbacks on this connection */
iRet = LLDnodePtr2First(pVictim->iList);
while(iRet != 0)
{
LLDnodeDataTo(pVictim->iList,&sItem);
RemoveCallback(sItem.pInterface, sItem.lID);
iRet = LLDnodePtr2Next(pVictim->iList);
}
LLDdelete(pVictim->iList);
/* remove standing data connections */
if(pVictim->pDataSock)
{
NETClosePort(pVictim->pDataSock);
free(pVictim->pDataSock);
free(pVictim->pDataComp);
}
/* remove command stack */
if(pVictim->pStack)
{
DeleteCommandStack(pVictim->pStack);
}
/* finally free pVictim*/
free(pVictim);
}
/*---------------------------------------------------------------------------*/
static int HasNL(char *buffer)
{
int i;
for(i = strlen(buffer); i > 0; i--)
{
if(isprint(buffer[i]))
{
break;
}
if(buffer[i] == '\n')
{
return 1;
}
}
return 0;
}
/*-------------------------------------------------------------------------
TelnetWrite makes sure, that all lines are properly terminated with a
<cr><lf> as required by the telnet protocoll.
There may be a problem here at long messages. 7.5.1998 MK
--------------------------------------------------------------------------*/
#define TXT 0
#define LF 1
int TelnetWrite(mkChannel *pSock, char *pBuffer)
{
char *pStart = NULL, *pPtr;
int iCount, iState;
pStart = pBuffer;
pPtr = pStart;
iState = TXT;
iCount = 0;
while(*pPtr != '\0')
{
switch(iState)
{
case TXT:
if( (*pPtr == '\r') || (*pPtr == '\n') )
{
iState = LF;
NETWrite(pSock,pStart,iCount);
NETWrite(pSock,"\r\n",2);
iCount = 0;
}
else
{
iCount++;
}
break;
case LF:
if( (*pPtr != '\r') && (*pPtr != '\n') )
{
pStart = pPtr;
iCount = 0;
iState = TXT;
}
else
{
/* do nothing */
}
break;
}
pPtr++;
}
if(iCount > 0)
{
NETWrite(pSock,pStart,iCount);
NETWrite(pSock,"\r\n",2);
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SCWrite(SConnection *self, char *pBuffer, int iOut)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->write(self,pBuffer,iOut);
}
/*--------------------------------------------------------------------------*/
static int SCNormalWrite(SConnection *self, char *buffer, int iOut)
{
int i, iPtr, iRet;
char pBueffel[80];
if(!VerifyConnection(self))
{
return 0;
}
/* log it for any case */
if(self->pSock)
{
iRet = self->pSock->sockid;
}
else
{
iRet = 0;
}
sprintf(pBueffel,"Next line intended for socket: %d",iRet);
SICSLogWrite(pBueffel,eInternal);
SICSLogWrite(buffer,iOut);
/* write to commandlog if user or manager privilege */
if(SCGetRights(self) <= usUser)
{
sprintf(pBueffel,"To sock %d :",iRet);
WriteToCommandLog(pBueffel,buffer);
}
/* put it into the interpreter if present */
if(SCinMacro(self))
{
InterpWrite(self->pSics,buffer);
/* print it to client if error message */
if((iOut== eError) || (iOut == eWarning) )
{
if(self->pSock)
{
if(self->iTelnet)
{
TelnetWrite(self->pSock,buffer);
}
else
{
iRet = NETWrite(self->pSock,buffer,strlen(buffer));
if(!HasNL(buffer))
{
iRet = NETWrite(self->pSock,"\n",sizeof("\n"));
}
}
}
else
{
puts(buffer);
}
}
}
else /* not in interpreter, normal logic */
{
/* is this really to be printed ? */
if(iOut < self->iOutput)
return 0;
/* first the socket */
if(self->pSock)
{
if(self->iTelnet)
{
TelnetWrite(self->pSock,buffer);
}
else
{
iRet = NETWrite(self->pSock,buffer,strlen(buffer));
if(!HasNL(buffer))
{
iRet = NETWrite(self->pSock,"\n",sizeof("\n"));
}
}
if(!iRet)
return 0;
}
else
{
printf("%s \n",buffer);
}
/* now all the possible logfiles */
for(i = 0; i < self->iFiles; i++)
{
if(self->pFiles[i])
{
fputs(buffer,self->pFiles[i]);
if(! HasNL(buffer))
{
fputs("\n",self->pFiles[i]);
fflush(self->pFiles[i]);
}
}
}
}
return 1;
}
/*--------------------------------------------------------------------------
This version writes only to configured log files but not to sockets.
Used for automatic file execution for the WWW interface
*/
static int SCFileWrite(SConnection *self, char *buffer, int iOut)
{
int i, iPtr, iRet;
char pBueffel[80];
if(!VerifyConnection(self))
{
return 0;
}
/* put into Serverlog */
sprintf(pBueffel,"Next line intended for socket: %d",-10);
SICSLogWrite(pBueffel,eInternal);
SICSLogWrite(buffer,iOut);
/* write to commandlog if user or manager privilege */
if(SCGetRights(self) <= usUser)
{
sprintf(pBueffel,"To sock %d :",-10);
WriteToCommandLog(pBueffel,buffer);
}
/* put it into the interpreter if present */
if(SCinMacro(self))
{
InterpWrite(self->pSics,buffer);
}
else /* not in interpreter, normal logic */
{
/* is this really to be printed ? */
if(iOut < self->iOutput)
return 0;
/* now all the possible logfiles */
for(i = 0; i < self->iFiles; i++)
{
if(self->pFiles[i])
{
fputs(buffer,self->pFiles[i]);
if(! HasNL(buffer))
{
fputs("\n",self->pFiles[i]);
fflush(self->pFiles[i]);
}
}
}
}
return 1;
}
/*-----------------------------------------------------------------------*/
int SCnoSock(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
self->write = SCFileWrite;
}
/*-------------------------------------------------------------------------*/
int SCWriteBinary(SConnection *pCon, char *pComputer, int iPort,
void *pData, int iDataLen)
{
int iRet;
char pBueffel[1024];
mkChannel *pChan = NULL;
assert(pCon);
/* do we have an identical connection already */
if(pCon->pDataSock)
{
if(strcmp(pComputer,pCon->pDataComp) == 0 && (pCon->iDataPort == iPort))
{
pChan = pCon->pDataSock;
}
else /* rubbish, kill it */
{
NETClosePort(pCon->pDataSock);
free(pCon->pDataSock);
free(pCon->pDataComp);
pCon->pDataSock = NULL;
pCon->pDataComp = NULL;
}
}
/* we have none, open it! */
if(!pChan)
{
pChan = NETConnect(pComputer, iPort);
if(!pChan)
{
sprintf(pBueffel,"ERROR: cannot connect to %s %d",pComputer, iPort);
SCWrite(pCon,pBueffel,eError);
SCWrite(pCon,"EOFBINARYERROR",eValue);
return 0;
}
pCon->pDataSock = pChan;
pCon->pDataComp = strdup(pComputer);
pCon->iDataPort = iPort;
}
/* do the writing */
iRet = NETWrite(pChan,pData,iDataLen);
if(iRet != 1)
{
sprintf(pBueffel,"ERROR: failed to write data to %s %d",pComputer, iPort);
SCWrite(pCon,pBueffel,eError);
SCWrite(pCon,"EOFBINARYERROR",eValue);
NETClosePort(pChan);
free(pCon->pDataSock);
free(pCon->pDataComp);
pCon->pDataSock = NULL;
pCon->pDataComp = NULL;
return 0;
}
SCWrite(pCon,"EOFBINARYOK",eValue);
return 1;
}
/*------------------------------------------------------------------------*/
int SCWriteUUencoded(SConnection *pCon, char *pName, void *pData, int iDataLen)
{
void *pPtr = NULL;
int iLength = 0;
int iRet;
FILE *fd;
iRet = UUencodeBuffer(pData,iDataLen,pName, &pPtr, &iLength);
if(iRet != 1)
{
SCWrite(pCon,"ERROR: no memory for uuencoder",eError);
return 0;
}
/* the uuencoder ensures proper telnet <cr><lf> */
if(pCon->iTelnet)
{
NETWrite(pCon->pSock,pPtr,iLength);
/* printf("Writing %d uuencoded characters\n",iLength); */
}
else
{
NETWrite(pCon->pSock,pPtr,iLength);
}
#ifdef UUDEB
fd = fopen("uubuffer.uu","w");
fputs(pPtr,fd);
fclose(fd);
#endif
free(pPtr);
return 1;
}
/*-------------------------------------------------------------------------*/
int SCSendOK(SConnection *self)
{
return SCWrite(self,"OK",eStatus);
}
/*--------------------------------------------------------------------------*/
int SCRead(SConnection *self, char *buffer, int iLen)
{
int iRet;
if(!VerifyConnection(self))
{
return 0;
}
if(self->pSock == NULL)
{
printf("SICS>> ");
fgets(buffer,iLen-1,stdin);
return 1;
}
if(self->pSock)
{
iRet = NETRead(self->pSock,buffer,iLen,10);
if(iRet == 0) /* no data */
{
return 0;
}
else if(iRet < 0) /* eof */
{
return EOF;
}
else /* data */
{
return 1;
}
}
else
{
return EOF;
/* fgets(buffer,iLen,stdin); */
}
return 1;
}
/*----------------------------------------------------------------------------*/
int SCMatchRights(SConnection *pCon, int iCode)
{
char pBueffel[132];
if(!VerifyConnection(pCon))
{
return 0;
}
if(iCode < SCGetRights(pCon))
{
sprintf(pBueffel,"ERROR: you are not authorised for this operation");
SCWrite(pCon, pBueffel, eError);
return 0;
}
if(pCon->iGrab)
{
sprintf(pBueffel,"ERROR: Request refused, control has been grabbed by somebody else");
SCWrite(pCon,pBueffel,eError);
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen)
{
int iRet, i;
char *pPtr = NULL;
Status eOld;
if(!VerifyConnection(pCon))
{
return 0;
}
SCWrite(pCon,pPrompt,eWarning);
eOld = GetStatus();
SetStatus(eInput);
CostaUnlock(pCon->pStack);
while(1)
{
/* wait a second */
SicsWait(1);
/* is there an interrupt pending ? */
if(SCGetInterrupt(pCon) != eContinue)
{
break;
}
/* do we have data ? */
iRet = CostaPop(pCon->pStack,&pPtr);
if(iRet == 1)
{
SetStatus(eOld);
CostaLock(pCon->pStack);
strncpy(pResult,pPtr,iLen);
return 1;
}
}
SetStatus(eOld);
CostaLock(pCon->pStack);
return 0;
}
/*---------------------------------------------------------------------------*/
int SCGetRights(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->iUserRights;
}
/*---------------------------------------------------------------------------*/
int SCGetGrab(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->iGrab;
}
/*--------------------------------------------------------------------------*/
int SCSetRights(SConnection *self, int iNew)
{
if(!VerifyConnection(self))
{
return 0;
}
assert(iNew >= usInternal);
assert(iNew <= usSpy);
self->iUserRights = iNew;
return 1;
}
/*---------------------------------------------------------------------------*/
int SCGetOutClass(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->iOutput;
}
/*--------------------------------------------------------------------------*/
void SCSetInterrupt(SConnection *self, int eCode)
{
if(!VerifyConnection(self))
{
return;
}
self->eInterrupt = eCode;
}
/*---------------------------------------------------------------------------*/
int SCGetInterrupt(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->eInterrupt;
}
/*--------------------------------------------------------------------------*/
void SCSetError(SConnection *self, int eCode)
{
if(!VerifyConnection(self))
{
return;
}
self->iErrCode = eCode;
}
/*---------------------------------------------------------------------------*/
int SCGetError(SConnection *self)
{
if(!VerifyConnection(self))
{
return 0;
}
return self->iErrCode;
}
/* --------------------------------------------------------------------------*/
int SCInvoke(SConnection *self, SicsInterp *pInter, char *pCommand)
{
int iRet;
long lLen;
const char *pResult = NULL;
char *pBuffer = NULL;
char pBueffel[80];
int i, iSpace;
if(!VerifyConnection(self))
{
return 0;
}
assert(pInter);
/* print command to log files */
for( i = 0; i < self->iFiles; i++)
{
if(self->pFiles[i])
{
fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
}
}
/* print to command log if user or manager */
if(SCGetRights(self) <= usUser)
{
if(self->pSock != NULL)
{
sprintf(pBueffel,"sock %d>>",self->pSock->sockid);
}
else
{
strcat(pBueffel,"CONT or CRON>> ");
}
WriteToCommandLog(pBueffel,pCommand);
}
/* invoke */
self->inUse++;
self->eInterrupt = eContinue;
self->iErrCode = OKOK;
iRet = InterpExecute(pInter,self,pCommand);
self->inUse--;
return iRet;
}
/*---------------------------------------------------------------------------
For configuring connections. Syntax:
config OutCode val sets an new output code
config Rights User Password sets and verifies new user rights
config File Filename Logs to another file
*/
#include "outcode.c" /* text for OutCode */
int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[512];
int i, iRet;
int iNum;
if(!VerifyConnection(pCon))
{
return 0;
}
assert(pSics);
/* check no of args */
if(argc < 2)
{
sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* handle list*/
strtolower(argv[1]);
if(strcmp(argv[1],"list") == 0)
{
sprintf(pBueffel,"OutCode = %s",pCode[pCon->iOutput]);
SCWrite(pCon,pBueffel,eStatus);
sprintf(pBueffel,"UserRights = %d",SCGetRights(pCon));
SCWrite(pCon,pBueffel,eStatus);
return 1;
}
else if(strcmp(argv[1],"myname") == 0)
{
sprintf(pBueffel,"MyName = %s",pCon->pName);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
else if(strcmp(argv[1],"myrights") == 0)
{
sprintf(pBueffel,"UserRights = %d",SCGetRights(pCon));
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/* check no or args */
if(argc < 3)
{
sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
SCWrite(pCon,pBueffel,eInError);
return 0;
}
/* decide what to do */
if(strcmp(argv[1],"file") == 0)
{
iRet = SCAddLogFile(pCon,argv[2]);
if(iRet >= 0 )
{
sprintf(pBueffel,"File = %d",iRet);
SCWrite(pCon,pBueffel,eStatus);
return 1;
}
}
if(strcmp(argv[1],"close") == 0) /* close file */
{
iNum = atoi(argv[2]);
if( (iNum >= 0) && (iNum < MAXLOGFILES))
{
if(pCon->pFiles[iNum])
{
fclose(pCon->pFiles[iNum]);
pCon->pFiles[iNum] = NULL;
SCSendOK(pCon);
return 1;
}
}
else
{
SCWrite(pCon, "Invalid file number specified ",eError);
return 0;
}
}
else if(strcmp(argv[1],"outcode") == 0)
{
i = 0;
strtolower(argv[2]);
while(pCode[i] != NULL)
{
if(strcmp(pCode[i],argv[2]) == 0)
{
break;
}
i++;
}
if( i > iNoCodes)
{
sprintf(pBueffel,"OutCode %s not recognized",argv[2]);
SCWrite(pCon,pBueffel,eInError);
return 0;
}
pCon->iOutput = i;
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[1],"rights") == 0)
{
if(argc < 4)
{
sprintf(pBueffel,"Insufficient number of args to %s",argv[0]);
SCWrite(pCon,pBueffel,eInError);
return 0;
}
i = IsValidUser(argv[2],argv[3]);
if(i < 0)
{
sprintf(pBueffel," %s with password ****** is NO valid User on SICS",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pCon->iUserRights = i;
sprintf(pBueffel,"User %s socket %d switched to %d privilege",
argv[2],pCon->pSock->sockid,i);
WriteToCommandLog("SYS>",pBueffel);
SCWrite(pCon,"Change of Authorisation Acknowledged",eWarning);
return 1;
}
SCWrite(pCon,"Command not recognized",eError);
return 0;
}
/*----------------------------------------------------------------------*/
int SCRegister(SConnection *pCon, SicsInterp *pSics,
void *pData, long lID)
{
pICallBack pInter = NULL;
Item sItem;
pInter = (pICallBack)pData;
if(!VerifyConnection(pCon))
{
return 0;
}
assert(pSics);
assert(pInter);
sItem.lID = lID;
sItem.pInterface = pInter;
LLDnodeAppendFrom(pCon->iList,&sItem);
return 1;
}
/*----------------------------------------------------------------------*/
int SCUnregister(SConnection *pCon, void *pData)
{
int iRet;
Item sItem;
pICallBack pInter;
if(!VerifyConnection(pCon))
{
return 0;
}
pInter = (pICallBack)pData;
iRet = LLDnodePtr2First(pCon->iList);
while(iRet != 0)
{
LLDnodeDataTo(pCon->iList,&sItem);
if(sItem.pInterface == pInter)
{
LLDnodeDelete(pCon->iList);
LLDnodePtr2Prev(pCon->iList);
}
iRet = LLDnodePtr2Next(pCon->iList);
}
return 1;
}
/*---------------------- The callback data structure --------------------*/
typedef struct {
SConnection *pCon;
SicsInterp *pSics;
char *pAction;
} CBAction, *pCBAction;
/*---------------------- CBKill -----------------------------------------*/
static void CBKill(void *pData)
{
pCBAction self = NULL;
self = (pCBAction)pData;
if(self == NULL)
{
return;
}
if(self->pAction)
{
free(self->pAction);
}
free(self);
}
/*-------------------------------------------------------------------------
The callback function for connection callbacks. Invokes command
given at registration time.
*/
static int ConCallBack(int iEvent, void *pEventData, void *pUserData)
{
pCBAction self = NULL;
self = (pCBAction)pUserData;
assert(self);
if(self->pAction)
{
InterpExecute(self->pSics,self->pCon,self->pAction);
}
return 1;
}
/*--------------------------------------------------------------------------
The only command currently understood is: put args
writes the args to the client
*/
int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
SConnection *self = NULL;
pICallBack pInterface = NULL;
char pBueffel[1024];
pDummy pDum;
int iEvent;
Item sItem;
pCBAction pCB = NULL;
CommandList *pCom = NULL;
int iMacro;
self = (SConnection *)pData;
if(!VerifyConnection(self))
{
return 0;
}
if(argc > 1)
{
/* put */
if(strcmp(argv[1],"put") == 0)
{
Arg2Text(argc-2,&argv[2],pBueffel,1023);
iMacro = SCinMacro(pCon);
SCsetMacro(pCon,0);
SCWrite(self,pBueffel,eWarning);
SCsetMacro(pCon,iMacro);
return 1;
}
/* register object event action */
if(strcmp(argv[1],"register") == 0)
{
if(argc < 5)
{
SCWrite(pCon,"ERROR: Insufficient arguments to register",eError);
return 0;
}
/* get object */
pCom = FindCommand(pSics,argv[2]);
if(!pCom)
{
sprintf(pBueffel,"ERROR: object %s NOT found",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* get CallBack interface */
pDum = (pDummy)pCom->pData;
assert(pDum);
pInterface = (pICallBack)pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE);
if(!pInterface)
{
sprintf(pBueffel,"ERROR: %s does not support CallBacks",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* get Event */
iEvent = Text2Event(argv[3]);
if(iEvent < 0)
{
sprintf(pBueffel,"ERROR: Unknown event code %s",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* now we can install the callback */
pCB = (pCBAction)malloc(sizeof(CBAction));
if(!pCB)
{
SCWrite(pCon,"ERROR: memory exhausted in SConnection",eError);
return 0;
}
Arg2Text(argc-4, &argv[4],pBueffel,1023);
pCB->pCon = pCon;
pCB->pSics = pSics;
pCB->pAction = strdup(pBueffel);
sItem.pInterface = pInterface;
sItem.lID = RegisterCallback(pInterface, iEvent, ConCallBack,
pCB, CBKill);
LLDnodeAppendFrom(self->iList,&sItem);
SCSendOK(pCon);
return 1;
}
}
return 0;
}
/*--------------------------------------------------------------------------*/
int SCTaskFunction(void *pData)
{
SConnection *self = NULL;
char *pPtr = NULL;
int iRet;
self = (SConnection *)pData;
if(!VerifyConnection(self))
{
return 0;
}
if(self->iEnd)
{
return 0;
}
/* pop and execute */
iRet = CostaPop(self->pStack,&pPtr);
if(iRet)
{
if(pPtr)
{
CostaLock(self->pStack);
SCInvoke(self,self->pSics,pPtr);
CostaUnlock(self->pStack);
/* SCWrite(self,"\b",eError); */
free(pPtr);
}
}
if(self->iEnd)
{
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
void SCSignalFunction(void *pData, int iSignal, void *pSigData)
{
SConnection *self = NULL;
int *iInt;
char *pPtr;
self = (SConnection *)pData;
if(!VerifyConnection(self))
{
return;
}
if(iSignal == SICSINT)
{
iInt = (int *)pSigData;
SCSetInterrupt(self,*iInt);
if(*iInt == eEndServer)
{
self->iEnd = 1;
}
}
else if(iSignal == SICSBROADCAST)
{
pPtr = (char *)pSigData;
if(pPtr)
{
SCWrite(self,pPtr,eWarning);
}
}
else if(iSignal == TOKENRELEASE)
{
self->iGrab = 0;
}
else if(iSignal == TOKENGRAB)
{
self->iGrab = 1;
}
}