2405 lines
61 KiB
C
2405 lines
61 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
|
|
|
|
Revamped login to non telnet connection.
|
|
Added compressed writing method.
|
|
Mark Koennecke, October 2000
|
|
|
|
Added simulation mode
|
|
Mark Koennecke, March 2003
|
|
|
|
Refactored a bit, removed SCWriteBinary (never used anywhere), added
|
|
appending outcode to text,
|
|
Mark Koennecke, July 2004
|
|
|
|
Made use of unused connections secure (connections are not
|
|
freed, but reused on new connections).
|
|
Introduced new type SCStore and functions SCSave, SCLoad.
|
|
Introduced SCPrintf to avoid many of these pBueffel.
|
|
Markus Zolliker, Sept 2004.
|
|
|
|
Cleaned up conman data structure. Removed left over and unused
|
|
fields.
|
|
Mark Koennecke, December 2004
|
|
|
|
Aded buffering support, Mark Koennecke, July 2006
|
|
|
|
Copyright: see copyright.h
|
|
-----------------------------------------------------------------------------*/
|
|
#include "fortify.h"
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <zlib.h>
|
|
#include <tcl.h>
|
|
#include <time.h>
|
|
#include <limits.h>
|
|
#include <stdarg.h>
|
|
#include "lld.h"
|
|
#include "sics.h"
|
|
#include "passwd.h"
|
|
#include "splitter.h"
|
|
#include "macro.h"
|
|
#include "servlog.h"
|
|
#include "status.h"
|
|
#include "interrupt.h"
|
|
#include "ifile.h"
|
|
#include "token.h"
|
|
#include "uubuffer.h"
|
|
#include "commandlog.h"
|
|
#include "stptok.h"
|
|
#include "statusfile.h"
|
|
#include "sicshipadaba.h"
|
|
#include "protocol.h"
|
|
/*
|
|
#define UUDEB 1
|
|
define UUDEB , for buffer writing for checking encoding */
|
|
|
|
extern pServer pServ;
|
|
|
|
#include "outcode.c" /* text for OutCode */
|
|
|
|
|
|
/*------ Max Size of Command Stack */
|
|
#define MAXSTACK 1024
|
|
/*---------- 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 SConnection *freeConnections = NULL;
|
|
static long lastIdent = 0;
|
|
/*------------- sending connection (prevent double write when listening) ----*/
|
|
static SConnection *sendingConnection = NULL;
|
|
/*------------- storing connection and context for later use ----*/
|
|
struct SCStore {
|
|
SConnection *pCon;
|
|
long ident;
|
|
int inMacro;
|
|
int inMacroSave;
|
|
int pushLevel;
|
|
commandContext cc;
|
|
};
|
|
/*===========================================================================*/
|
|
static char *ConName(long ident) {
|
|
static char name[32];
|
|
snprintf(name, sizeof(name), "CON%ld", ident);
|
|
return name;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void FreeConnection(SConnection *pCon)
|
|
{
|
|
memset(pCon,0,sizeof(SConnection));
|
|
pCon->ident = 0;
|
|
pCon->next = freeConnections;
|
|
pCon->listening = 0;
|
|
freeConnections = pCon;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static SConnection *CreateConnection(SicsInterp *pSics)
|
|
{
|
|
int i;
|
|
SConnection *pRes = NULL;
|
|
char pBueffel[253];
|
|
char pHost[132];
|
|
|
|
if (!freeConnections)
|
|
{ /* no more free connection: get one by malloc */
|
|
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));
|
|
}
|
|
else
|
|
{ /* reuse an old connection */
|
|
pRes = freeConnections;
|
|
freeConnections = pRes->next;
|
|
}
|
|
|
|
do
|
|
{ /* loop until an unused ident is found. This test needed only for
|
|
the case there some object has already the name con<nnn>.
|
|
In a live cycle of SICS, no connection ever can get an earlier
|
|
used name */
|
|
if (lastIdent == LONG_MAX)
|
|
{
|
|
/* This is a serious, very serious error! */
|
|
SICSLogWrite("ERROR: Run out of connection identifiers!!",eInternal);
|
|
return NULL;
|
|
}
|
|
lastIdent++;
|
|
} while (FindCommand(pSics, ConName(lastIdent)));
|
|
pRes->ident = lastIdent;
|
|
|
|
/* a descriptor */
|
|
pRes->pDes = CreateDescriptor("Connection");
|
|
if(!pRes->pDes)
|
|
{
|
|
/* This is a serious, very serious error! */
|
|
SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal);
|
|
FreeConnection(pRes);
|
|
return NULL;
|
|
}
|
|
|
|
/* 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);
|
|
FreeConnection(pRes);
|
|
return NULL;
|
|
}
|
|
|
|
pRes->iOutput = eInError; /* gets everything except internal messages */
|
|
pRes->iFiles = 0; /* default: no logfiles */
|
|
pRes->inUse = 0;
|
|
pRes->iMacro = 0;
|
|
pRes->iTelnet = 0;
|
|
pRes->eInterrupt = eContinue;
|
|
pRes->lMagic = CONMAGIC;
|
|
pRes->iLogin = 0;
|
|
pRes->listening = 0;
|
|
pRes->conStart = time(NULL);
|
|
pRes->write = SCNormalWrite;
|
|
for(i = 0; i < 10; i++)
|
|
{
|
|
pRes->pFiles[i] = NULL;
|
|
}
|
|
|
|
/* initialise context variables */
|
|
pRes->iCmdCtr = 0;
|
|
pRes->conEventType=-1;
|
|
pRes->conStatus=-1;
|
|
pRes->contextStack = LLDcreate(sizeof(commandContext));
|
|
|
|
/* install command */
|
|
AddCommand(pSics, ConName(pRes->ident), ConSicsAction, NULL,pRes);
|
|
return pRes;
|
|
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser)
|
|
{
|
|
SConnection *pRes = NULL;
|
|
char pBueffel[253];
|
|
char pHost[132];
|
|
|
|
assert(pSock);
|
|
|
|
pRes = CreateConnection(pSics);
|
|
|
|
SetCommandStackMaxSize(pRes->pStack,MAXSTACK);
|
|
|
|
pRes->pSock = pSock;
|
|
pRes->iUserRights = iUser;
|
|
pRes->iGrab = TokenGrabActive();
|
|
|
|
|
|
return pRes;
|
|
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SConnection *SCCreateDummyConnection(SicsInterp *pSics)
|
|
{
|
|
SConnection *pRes = NULL;
|
|
|
|
pRes = CreateConnection(pSics);
|
|
|
|
pRes->pSock = NULL;
|
|
pRes->iUserRights = usInternal;
|
|
pRes->iGrab = 0;
|
|
|
|
SICSLogWrite("Accepted dummy connection ",eInternal);
|
|
|
|
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;
|
|
pHdb root = NULL;
|
|
|
|
pVictim = (SConnection *)pData;
|
|
if(!VerifyConnection(pVictim))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(SCActive(pVictim))
|
|
{
|
|
SCnoSock(pVictim);
|
|
if(pVictim->pSock)
|
|
{
|
|
NETClosePort(pVictim->pSock);
|
|
free(pVictim->pSock);
|
|
pVictim->pSock = NULL;
|
|
}
|
|
WriteToCommandLog("SYS>",
|
|
"ERROR: Erraneous deletion of used Connection stopped");
|
|
return;
|
|
}
|
|
|
|
|
|
/* remove the connection from the server log if it has captured
|
|
something
|
|
*/
|
|
KillCapture(pVictim);
|
|
|
|
/*
|
|
* remove any callbacks which might still be active in the Hipadaba
|
|
*/
|
|
root = GetHipadabaRoot();
|
|
if(root != NULL)
|
|
{
|
|
RemoveConnectionCallbacks(root,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 && pVictim->iLogin == 1 &&
|
|
(pVictim->iUserRights < 3 || !CompactCommandLog()) )
|
|
{
|
|
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++)
|
|
{
|
|
if(pVictim->pFiles[i] != NULL)
|
|
{
|
|
fclose(pVictim->pFiles[i]);
|
|
}
|
|
}
|
|
|
|
RemoveCommand(pServ->pSics,ConName(pVictim->ident));
|
|
|
|
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 command stack */
|
|
if(pVictim->pStack)
|
|
{
|
|
DeleteCommandStack(pVictim->pStack);
|
|
}
|
|
|
|
/* remove possible buffers */
|
|
if(pVictim->data != NULL)
|
|
{
|
|
DeleteDynString(pVictim->data);
|
|
}
|
|
|
|
pVictim->lMagic=0; /* make a write to a freed connection harmless */
|
|
/* finally free pVictim*/
|
|
LLDdelete(pVictim->contextStack);
|
|
FreeConnection(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;
|
|
int iRet = 1;
|
|
|
|
pStart = pBuffer;
|
|
pPtr = pStart;
|
|
iState = TXT;
|
|
iCount = 0;
|
|
while(*pPtr != '\0')
|
|
{
|
|
switch(iState)
|
|
{
|
|
case TXT:
|
|
if( (*pPtr == '\r') || (*pPtr == '\n') )
|
|
{
|
|
iState = LF;
|
|
iRet = NETWrite(pSock,pStart,iCount);
|
|
iRet = NETWrite(pSock,"\r\n",2);
|
|
iCount = 0;
|
|
}
|
|
else
|
|
{
|
|
iCount++;
|
|
}
|
|
break;
|
|
case LF:
|
|
if( (*pPtr != '\r') && (*pPtr != '\n') )
|
|
{
|
|
pStart = pPtr;
|
|
iCount = 1;
|
|
iState = TXT;
|
|
}
|
|
else
|
|
{
|
|
/* do nothing */
|
|
}
|
|
break;
|
|
}
|
|
pPtr++;
|
|
}
|
|
if(iCount > 0)
|
|
{
|
|
iRet = NETWrite(pSock,pStart,iCount);
|
|
iRet = NETWrite(pSock,"\r\n",2);
|
|
}
|
|
return iRet;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SCWrite(SConnection *self, char *pBuffer, int iOut)
|
|
{
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
/*
|
|
Do not die if no data
|
|
*/
|
|
if(pBuffer == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
return self->write(self,pBuffer,iOut);
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SCWriteInContext(SConnection *pCon, char *pBuffer, int out, commandContext cc)
|
|
{
|
|
int status;
|
|
SCPushContext2(pCon,cc);
|
|
status = SCWrite(pCon,pBuffer,out);
|
|
SCPopContext(pCon);
|
|
return status;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SCPrintf(SConnection *self, int iOut, char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char buf[256];
|
|
char *dyn;
|
|
int l;
|
|
int res;
|
|
|
|
va_start(ap, fmt);
|
|
l = vsnprintf(buf, sizeof buf, fmt, ap);
|
|
va_end(ap);
|
|
if (l >= sizeof buf) {
|
|
/* we have probably a C99 conforming snprintf and
|
|
need a larger buffer
|
|
*/
|
|
dyn = malloc(l+1);
|
|
if (dyn != NULL) {
|
|
va_start(ap, fmt);
|
|
vsnprintf(dyn, l+1, fmt, ap);
|
|
va_end(ap);
|
|
res = SCWrite(self, dyn, iOut);
|
|
free(dyn);
|
|
return res;
|
|
}
|
|
}
|
|
return SCWrite(self, buf, iOut);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
writeFunc SCGetWriteFunc(SConnection *self)
|
|
{
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
return self->write;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void SCSetWriteFunc(SConnection *self, writeFunc x)
|
|
{
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return;
|
|
}
|
|
self->write = x;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int doSockWrite(SConnection *self, char *buffer)
|
|
{
|
|
int iRet = 1;
|
|
|
|
if(self->pSock)
|
|
{
|
|
if(self->iTelnet)
|
|
{
|
|
iRet = TelnetWrite(self->pSock,buffer);
|
|
}
|
|
else
|
|
{
|
|
iRet = NETWrite(self->pSock,buffer,strlen(buffer));
|
|
if(!HasNL(buffer))
|
|
{
|
|
iRet = NETWrite(self->pSock,"\n",strlen("\n"));
|
|
}
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCnoSock(self);
|
|
if(!self->listening && self->iLogin == 1 &&
|
|
(self->iUserRights < 3 || !CompactCommandLog()) )
|
|
{
|
|
WriteToCommandLog("SYS>","Connection broken on send");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (HasNL(buffer)) {
|
|
fputs(buffer, stdout);
|
|
} else {
|
|
puts(buffer);
|
|
}
|
|
}
|
|
return iRet;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static void writeToLogFiles(SConnection *self, char *buffer)
|
|
{
|
|
int i;
|
|
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]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCNormalWrite(SConnection *self, char *buffer, int iOut)
|
|
{
|
|
int i, iPtr, iRet;
|
|
char pBueffel[80];
|
|
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
|
|
return 1; /* do not write empty line */
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
if(self->iMacro != 1)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
else
|
|
{
|
|
if(iOut == eError || iOut == eWarning)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
/* print it to client if error message */
|
|
if((iOut== eError) || (iOut == eWarning) )
|
|
{
|
|
iRet = doSockWrite(self,buffer);
|
|
}
|
|
}
|
|
else /* not in interpreter, normal logic */
|
|
{
|
|
/* is this really to be printed ? */
|
|
if(iOut < self->iOutput)
|
|
return 0;
|
|
|
|
/* first the socket */
|
|
iRet = doSockWrite(self,buffer);
|
|
|
|
writeToLogFiles(self,buffer);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCACTWrite(SConnection *self, char *buffer, int iOut)
|
|
{
|
|
int i, iPtr, iRet;
|
|
char pBueffel[1024];
|
|
char *pPtr = pBueffel;
|
|
commandContext cx;
|
|
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
|
|
return 1; /* do not write empty line */
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
if(self->iMacro != 1)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
else
|
|
{
|
|
if(iOut == eError || iOut == eWarning)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* copy in ACT
|
|
*/
|
|
if(strlen(buffer) + 30 > 1024){
|
|
pPtr = (char *)malloc((strlen(buffer)+30)*sizeof(char));
|
|
memset(pPtr,0,strlen(buffer)+20);
|
|
}
|
|
cx = SCGetContext(self);
|
|
sprintf(pPtr,"%d::>%s<::", cx.transID, buffer);
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
/* print it to client if error message */
|
|
if((iOut== eError) || (iOut == eWarning) )
|
|
{
|
|
iRet = doSockWrite(self,pPtr);
|
|
}
|
|
}
|
|
else /* not in interpreter, normal logic */
|
|
{
|
|
/* is this really to be printed ? */
|
|
if(iOut < self->iOutput)
|
|
return 0;
|
|
|
|
/* first the socket */
|
|
iRet = doSockWrite(self,pPtr);
|
|
|
|
writeToLogFiles(self,buffer);
|
|
}
|
|
if(pPtr != pBueffel){
|
|
free(pPtr);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut)
|
|
{
|
|
int i, iPtr, iRet, length;
|
|
char pBueffel[80];
|
|
char *bufPtr = NULL;
|
|
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (buffer[0] == '\0' && iOut >= eStart && iOut <= eEvent) {
|
|
return 1; /* do not write empty line */
|
|
}
|
|
|
|
/* 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 && self->iMacro != 1)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
|
|
/*
|
|
prepare the message with the outcode appended.
|
|
*/
|
|
length = strlen(buffer) + strlen(pCode[iOut]) + 10;
|
|
bufPtr = (char *)malloc(length * sizeof(char));
|
|
if(!bufPtr)
|
|
{
|
|
SICSLogWrite("SYS>>ERROR: out of memory in SCWriteWithOutcode",eError);
|
|
return 0;
|
|
}
|
|
memset(bufPtr,0,length*sizeof(char));
|
|
strcpy(bufPtr,buffer);
|
|
i = strlen(bufPtr);
|
|
while(i-- > 0)
|
|
{
|
|
if(!isspace(bufPtr[i]))
|
|
break;
|
|
}
|
|
i++;
|
|
bufPtr[i] = '\0';
|
|
strcat(bufPtr,"@@");
|
|
strcat(bufPtr,pCode[iOut]);
|
|
strcat(bufPtr,"\r\n");
|
|
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
/* print it to client if error message */
|
|
if((iOut== eError) || (iOut == eWarning) )
|
|
{
|
|
iRet = doSockWrite(self,bufPtr);
|
|
}
|
|
}
|
|
else /* not in interpreter, normal logic */
|
|
{
|
|
/* is this really to be printed ? */
|
|
if(iOut < self->iOutput)
|
|
{
|
|
free(bufPtr);
|
|
return 0;
|
|
}
|
|
|
|
/* first the socket */
|
|
iRet = doSockWrite(self,bufPtr);
|
|
|
|
writeToLogFiles(self,buffer);
|
|
}
|
|
free(bufPtr);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int SCBufferWrite(SConnection *self, char *buffer, int iOut)
|
|
{
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
assert(self->data != NULL);
|
|
DynStringConcat(self->data,buffer);
|
|
if(strchr(buffer,'\n') == NULL){
|
|
DynStringConcat(self->data,"\n");
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SCStartBuffering(SConnection *pCon)
|
|
{
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return 0;
|
|
}
|
|
if(pCon->data != NULL)
|
|
{
|
|
DeleteDynString(pCon->data);
|
|
}
|
|
pCon->data = CreateDynString(128,128);
|
|
if(pCon->data == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
pCon->oldWriteFunc = pCon->write;
|
|
pCon->write = SCBufferWrite;
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pDynString SCEndBuffering(SConnection *pCon)
|
|
{
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return 0;
|
|
}
|
|
assert(pCon->oldWriteFunc != NULL);
|
|
pCon->write = pCon->oldWriteFunc;
|
|
pCon->oldWriteFunc = NULL;
|
|
return pCon->data;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCOnlySockWrite(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);
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
}
|
|
else /* not in interpreter, normal logic */
|
|
{
|
|
/* is this really to be printed ? */
|
|
if(iOut < self->iOutput)
|
|
return 0;
|
|
|
|
/* the socket */
|
|
iRet = doSockWrite(self,buffer);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCNotWrite(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);
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------
|
|
This version writes only to configured log files but not to sockets.
|
|
Used for automatic file execution for the WWW interface
|
|
*/
|
|
int SCFileWrite(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 = -10;
|
|
}
|
|
|
|
/* put into Serverlog */
|
|
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)
|
|
{
|
|
if(self->iMacro != 1)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
else
|
|
{
|
|
if(iOut == eError || iOut == eWarning)
|
|
{
|
|
sendingConnection = self;
|
|
WriteToCommandLogId(NULL,iRet,buffer);
|
|
sendingConnection = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* put it into the interpreter if present */
|
|
if(SCinMacro(self))
|
|
{
|
|
InterpWrite(pServ->pSics,buffer);
|
|
}
|
|
else /* not in interpreter, normal logic */
|
|
{
|
|
/* is this really to be printed ? */
|
|
if(iOut < self->iOutput)
|
|
return 0;
|
|
|
|
writeToLogFiles(self,buffer);
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SCnoSock(SConnection *self)
|
|
{
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
self->write = SCFileWrite;
|
|
return 0;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SCWriteUUencoded(SConnection *pCon, char *pName, void *pData,
|
|
int iDataLen)
|
|
{
|
|
void *pPtr = NULL;
|
|
int iLength = 0;
|
|
int iRet = 1;
|
|
FILE *fd;
|
|
char *pTest;
|
|
|
|
iRet = UUencodeBuffer(pData,iDataLen,pName, &pPtr, &iLength);
|
|
if(iRet != 1)
|
|
{
|
|
SCWrite(pCon,"ERROR: no memory for uuencoder",eError);
|
|
return 0;
|
|
}
|
|
pTest = (char *)pPtr;
|
|
|
|
/* the uuencoder ensures proper telnet <cr><lf> */
|
|
if(pCon->iTelnet)
|
|
{
|
|
NETWrite(pCon->pSock,pPtr,iLength);
|
|
}
|
|
else
|
|
{
|
|
NETWrite(pCon->pSock,pPtr,iLength);
|
|
}
|
|
|
|
#ifdef UUDEB
|
|
fd = fopen("uubuffer.uu","w");
|
|
fputs(pPtr,fd);
|
|
fclose(fd);
|
|
#endif
|
|
|
|
free(pPtr);
|
|
return iRet;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
#define ZIPBUF 8192
|
|
int SCWriteZipped(SConnection *self, char *pName, void *pData, int iDataLen)
|
|
{
|
|
char outBuf[65546], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL;
|
|
int compressedLength, iRet, iRet2, iCount, protocolID;
|
|
z_stream compStream;
|
|
commandContext cc;
|
|
|
|
/* check for a valid connection */
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* a telnet connection will corrupt the compressed stream, so
|
|
stop it!
|
|
*/
|
|
if(self->iTelnet)
|
|
{
|
|
SCWrite(self,
|
|
"ERROR: the telnet protocoll will currupt compressed data!",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
do nothing if no data
|
|
*/
|
|
if(pName == NULL || pData == NULL)
|
|
{
|
|
SCWrite(self,"ERROR: no data to write in SCWriteZiped",eError);
|
|
return 0;
|
|
}
|
|
|
|
/* initialize the compression stuff */
|
|
compStream.zalloc = (alloc_func)NULL;
|
|
compStream.zfree = (free_func)NULL;
|
|
compStream.opaque = (voidpf)NULL;
|
|
|
|
iRet = deflateInit(&compStream,Z_DEFAULT_COMPRESSION);
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* first pass: find out how the long the compressed buffer will be */
|
|
compressedLength = 0;
|
|
compStream.next_in = (Bytef *)pData;
|
|
compStream.next_out = (Bytef *)outBuf;
|
|
compStream.avail_in = iDataLen;
|
|
compStream.avail_out = 65536;
|
|
while(compStream.total_in < iDataLen)
|
|
{
|
|
iRet = deflate(&compStream,Z_NO_FLUSH);
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
compStream.next_out = (Bytef *)outBuf;
|
|
compStream.avail_out = 65536;
|
|
}
|
|
for(;;)
|
|
{
|
|
iRet = deflate(&compStream,Z_FINISH);
|
|
if(iRet == Z_STREAM_END) break;
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
}
|
|
compressedLength = compStream.total_out;
|
|
deflateEnd(&compStream);
|
|
|
|
/* write header line */
|
|
memset(outBuf,0,65536);
|
|
|
|
protocolID = GetProtocolID(self);
|
|
if(protocolID == 5){
|
|
cc = SCGetContext(self);
|
|
sprintf(outBuf,"SICSBIN ZIP %s %d %d\r\n",pName,
|
|
compressedLength, cc.transID);
|
|
} else {
|
|
sprintf(outBuf,"SICSBIN ZIP %s %d \r\n",pName,compressedLength);
|
|
}
|
|
pHeader = strdup(outBuf);
|
|
if(pHeader == NULL)
|
|
{
|
|
SCWrite(self,"ERROR: out of memory in SCWriteZipped",eError);
|
|
return 0;
|
|
}
|
|
|
|
/* now reset the deflater and do the same with writing data */
|
|
compStream.zalloc = (alloc_func)NULL;
|
|
compStream.zfree = (free_func)NULL;
|
|
compStream.opaque = (voidpf)NULL;
|
|
|
|
|
|
/*
|
|
This is writing everything in one go as I found that writing in
|
|
several chunks did not ensure that all the data arrived at the
|
|
Java side.
|
|
*/
|
|
|
|
iRet = deflateInit(&compStream,Z_DEFAULT_COMPRESSION);
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
|
|
pBuf = (char *)malloc((iDataLen + iDataLen/10 + 50)*sizeof(char));
|
|
memset(pBuf,0,(iDataLen + iDataLen/10 + 50)*sizeof(char) );
|
|
compStream.next_in = (Bytef *)pData;
|
|
compStream.next_out = (Bytef *)pBuf;
|
|
compStream.avail_in = iDataLen;
|
|
compStream.avail_out = iDataLen + iDataLen/10 + 50;
|
|
iRet = deflate(&compStream,Z_FINISH);
|
|
if(iRet != Z_STREAM_END)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
iRet = NETWrite(self->pSock,pHeader,strlen(pHeader));
|
|
iRet = NETWrite(self->pSock,pBuf,compStream.total_out);
|
|
if(iRet != 1)
|
|
{
|
|
sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
deflateEnd(&compStream);
|
|
free(pHeader);
|
|
free(pBuf);
|
|
|
|
|
|
/*
|
|
Writing smaller buffers. Seems not to be working properly
|
|
with Java.
|
|
*/
|
|
/*
|
|
compStream.next_in = (Bytef *)pData;
|
|
compStream.avail_in = iDataLen;
|
|
compStream.avail_out = ZIPBUF;
|
|
compStream.next_out = (Bytef *)noutBuf;
|
|
iCount = 0;
|
|
while(compStream.total_in < iDataLen)
|
|
{
|
|
iRet = deflate(&compStream,Z_NO_FLUSH);
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
iRet = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out);
|
|
if(iRet != 1)
|
|
{
|
|
sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
iCount += ZIPBUF - compStream.avail_out;
|
|
compStream.next_out = (Bytef *)noutBuf;
|
|
compStream.avail_out = ZIPBUF;
|
|
}
|
|
for(;;)
|
|
{
|
|
iRet = deflate(&compStream,Z_FINISH);
|
|
iRet2 = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out);
|
|
if(iRet2 != 1)
|
|
{
|
|
sprintf(outBuf,"ERROR: network error %d on zipped send",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
iCount += ZIPBUF - compStream.avail_out;
|
|
if(iRet == Z_STREAM_END) break;
|
|
if(iRet != Z_OK)
|
|
{
|
|
sprintf(outBuf,"ERROR: zlib error: %d",iRet);
|
|
SCWrite(self,outBuf,eError);
|
|
return 0;
|
|
}
|
|
compStream.next_out = (Bytef *)noutBuf;
|
|
compStream.avail_out = ZIPBUF;
|
|
}
|
|
deflateEnd(&compStream);
|
|
*/
|
|
|
|
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;
|
|
char pFrom[50];
|
|
Status eOld;
|
|
int oldMode;
|
|
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SCWrite(pCon,pPrompt,eWarning);
|
|
eOld = GetStatus();
|
|
SetStatus(eInput);
|
|
CostaUnlock(pCon->pStack);
|
|
while(1)
|
|
{
|
|
/*
|
|
wait a second. We want to wait even in a simulation, otherwise
|
|
we go into an endless loop. This is why there is the hack with
|
|
oldMode and pServ->simMode.
|
|
*/
|
|
oldMode = pServ->simMode;
|
|
pServ->simMode = 0;
|
|
SicsWait(1);
|
|
pServ->simMode = oldMode;
|
|
|
|
/* 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);
|
|
WriteToCommandLogId(" prompted>", pCon->pSock->sockid, pPtr);
|
|
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;
|
|
}
|
|
/*----------------------------------------------------------------*/
|
|
extern char *trim(char *in);
|
|
/* --------------------------------------------------------------------------*/
|
|
int SCInvoke(SConnection *self, SicsInterp *pInter, char *pCommand)
|
|
{
|
|
int iRet;
|
|
long lLen;
|
|
const char *pResult = NULL;
|
|
char *pBuffer = NULL, *pFile = 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)
|
|
{
|
|
/*
|
|
* This is a fix to suppress cron messages in the success
|
|
* case
|
|
*/
|
|
if(SCGetWriteFunc(self) != SCNotWrite)
|
|
{
|
|
sendingConnection = self;
|
|
if(self->pSock != NULL)
|
|
{
|
|
WriteToCommandLogCmd(self->pSock->sockid, pCommand);
|
|
} else {
|
|
WriteToCommandLog("CRON>>",pCommand);
|
|
}
|
|
sendingConnection = NULL;
|
|
}
|
|
}
|
|
|
|
/* invoke */
|
|
self->inUse++;
|
|
self->eInterrupt = eContinue;
|
|
/*
|
|
get first word of command
|
|
*/
|
|
memset(pBueffel,0,80);
|
|
stptok(trim(pCommand),pBueffel,79," ");
|
|
SCAdvanceContext(self,pBueffel);
|
|
iRet = InterpExecute(pInter,self,pCommand);
|
|
SCPopContext(self);
|
|
StatusFileTask(NULL); /* save changed parameters */
|
|
|
|
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
|
|
config output normal | withcode | ACT Sets output mode
|
|
config listen 0 | 1 enables commandlog listen mode
|
|
---------------------------------------------------------------------------*/
|
|
|
|
int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
char pBueffel[512];
|
|
char pHost[132];
|
|
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\nUserRights = %d",
|
|
pCode[pCon->iOutput], SCGetRights(pCon));
|
|
SCWrite(pCon,pBueffel,eStatus);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"myname") == 0)
|
|
{
|
|
sprintf(pBueffel,"MyName = %s",ConName(pCon->ident));
|
|
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;
|
|
}
|
|
else if(strcmp(argv[1],"listen") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
snprintf(pBueffel,511,"listen = %d", pCon->listening);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
pCon->listening = atoi(argv[2]);
|
|
if(pCon->listening != 0 && pCon->listening != 1)
|
|
{
|
|
pCon->listening = 0;
|
|
SCWrite(pCon,"ERROR: config listen only accepts 0 or 1 as arguments",eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
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],"output") == 0)
|
|
{
|
|
strtolower(argv[2]);
|
|
if(strcmp(argv[2],"normal") == 0)
|
|
{
|
|
SCSetWriteFunc(pCon,SCNormalWrite);
|
|
}
|
|
else if(strcmp(argv[2],"withcode") == 0)
|
|
{
|
|
SCSetWriteFunc(pCon,SCWriteWithOutcode);
|
|
}
|
|
else if(strcmp(argv[2],"act") == 0)
|
|
{
|
|
SCSetWriteFunc(pCon,SCACTWrite);
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"ERROT: output mode not recognised",eError);
|
|
return 0;
|
|
}
|
|
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;
|
|
}
|
|
if (CompactCommandLog()) {
|
|
if (pCon->iUserRights < 3 || i < 3) {
|
|
NETInfo(pCon->pSock,pHost,sizeof pHost);
|
|
sprintf(pBueffel,"User %s from %s switched to %d privilege",
|
|
argv[2],pHost,i);
|
|
WriteToCommandLogId("SYS>",pCon->pSock->sockid,pBueffel);
|
|
}
|
|
} else {
|
|
sprintf(pBueffel,"User %s socket %d switched to %d privilege",
|
|
argv[2],pCon->pSock->sockid,i);
|
|
WriteToCommandLog("SYS>",pBueffel);
|
|
}
|
|
pCon->iUserRights = i;
|
|
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;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
int SCUnregisterID(SConnection *pCon, long ID)
|
|
{
|
|
int iRet;
|
|
Item sItem;
|
|
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = LLDnodePtr2First(pCon->iList);
|
|
while(iRet != 0)
|
|
{
|
|
LLDnodeDataTo(pCon->iList,&sItem);
|
|
if(sItem.lID == ID )
|
|
{
|
|
LLDnodeDelete(pCon->iList);
|
|
LLDnodePtr2Prev(pCon->iList);
|
|
}
|
|
iRet = LLDnodePtr2Next(pCon->iList);
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
long SCgetCallbackID(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)
|
|
{
|
|
return sItem.lID;
|
|
}
|
|
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,
|
|
commandContext cc)
|
|
{
|
|
pCBAction self = NULL;
|
|
|
|
self = (pCBAction)pUserData;
|
|
assert(self);
|
|
|
|
if(self->pAction)
|
|
{
|
|
SCPushContext2(self->pCon,cc);
|
|
InterpExecute(pServ->pSics,self->pCon,self->pAction);
|
|
SCPopContext(self->pCon);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
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;
|
|
char *script;
|
|
|
|
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;
|
|
}
|
|
|
|
script = Arg2Tcl(argc-4, &argv[4], NULL, 0);
|
|
|
|
/* now we can install the callback */
|
|
pCB = (pCBAction)malloc(sizeof(CBAction));
|
|
if(!pCB || !script)
|
|
{
|
|
SCWrite(pCon,"ERROR: memory exhausted in SConnection",eError);
|
|
return 0;
|
|
}
|
|
pCB->pCon = pCon;
|
|
pCB->pSics = pSics;
|
|
pCB->pAction = script;
|
|
sItem.pInterface = pInterface;
|
|
sItem.lID = RegisterCallback(pInterface, SCGetContext(pCB->pCon), 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;
|
|
char *pUser = NULL, *pPassword = NULL;
|
|
char pHost[132], pBueffel[512];
|
|
|
|
self = (SConnection *)pData;
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
if(self->pSock->iType == 0)
|
|
{
|
|
NetReadRemove(pServ->pReader,self->pSock);
|
|
self->iEnd = 1;
|
|
}
|
|
|
|
if(self->iEnd)
|
|
{
|
|
if(SCActive(self))
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* a timeout check on logins */
|
|
if(!self->iLogin && time(NULL) > self->conStart + 120)
|
|
{
|
|
NetReadRemove(pServ->pReader,self->pSock);
|
|
SCWrite(self, "No valid login in two minutes, closing..",eError);
|
|
self->iEnd = 1;
|
|
return 1;
|
|
}
|
|
|
|
/* pop and execute */
|
|
iRet = CostaPop(self->pStack,&pPtr);
|
|
if(iRet)
|
|
{
|
|
if(pPtr)
|
|
{
|
|
if(self->iLogin)
|
|
{
|
|
/*
|
|
normal processing, logged in
|
|
but check for logoff
|
|
*/
|
|
if(strstr(pPtr,"logoff") != NULL)
|
|
{
|
|
NetReadRemove(pServ->pReader,self->pSock);
|
|
self->iEnd = 1;
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
/* invoke command */
|
|
CostaLock(self->pStack);
|
|
SCInvoke(self,pServ->pSics,pPtr);
|
|
CostaUnlock(self->pStack);
|
|
}
|
|
else
|
|
{
|
|
/* response for monit check */
|
|
if (strstr(pPtr,"How are you") == pPtr)
|
|
{
|
|
SCWrite(self,"I am fine",eError);
|
|
NetReadRemove(pServ->pReader,self->pSock);
|
|
self->iEnd = 1;
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
/* check for username and password */
|
|
pUser = strtok(pPtr," \t");
|
|
pPassword = strtok(NULL," \t\r\n");
|
|
iRet = IsValidUser(pUser,pPassword);
|
|
if(iRet >= 0)
|
|
{
|
|
SCWrite(self,"Login OK",eError);
|
|
self->iLogin = 1;
|
|
SCSetRights(self,iRet);
|
|
pHost[0] = '\0';
|
|
if (CompactCommandLog()) {
|
|
if (iRet < 3) {
|
|
NETInfo(self->pSock,pHost,131);
|
|
sprintf(pBueffel,"Accepted connection %s from %s as %s",
|
|
ConName(self->ident), pHost, pUser);
|
|
SICSLogWrite(pBueffel,eInternal);
|
|
WriteToCommandLogId("SYS>", self->pSock->sockid, pBueffel);
|
|
}
|
|
} else {
|
|
NETInfo(self->pSock,pHost,131);
|
|
sprintf(pBueffel,"Accepted connection %s on socket %d from %s",
|
|
ConName(self->ident), self->pSock->sockid, pHost);
|
|
SICSLogWrite(pBueffel,eInternal);
|
|
WriteToCommandLog("SYS >", pBueffel);
|
|
}
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(self,"ERROR: Bad login",eError);
|
|
printf("Bad login string %s\n", pPtr);
|
|
}
|
|
}
|
|
free(pPtr);
|
|
}
|
|
}
|
|
|
|
|
|
if(self->iEnd)
|
|
{
|
|
if(SCActive(self))
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
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 != NULL)
|
|
{
|
|
SCWrite(self,pPtr,eWarning);
|
|
}
|
|
}
|
|
else if(iSignal == COMLOG && self->listening == 1)
|
|
{
|
|
pPtr = (char *)pSigData;
|
|
if(pPtr != NULL && self != sendingConnection)
|
|
{
|
|
doSockWrite(self,pPtr);
|
|
}
|
|
}
|
|
else if(iSignal == TOKENRELEASE)
|
|
{
|
|
self->iGrab = 0;
|
|
}
|
|
else if(iSignal == TOKENGRAB)
|
|
{
|
|
self->iGrab = 1;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
void SCparChange(SConnection *self)
|
|
{
|
|
StatusFileDirty();
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SCActive(SConnection *self)
|
|
{
|
|
if(self->inUse != 0 )
|
|
{
|
|
return 1;
|
|
}
|
|
if(pServ->pExecutor != NULL)
|
|
{
|
|
if(GetExeOwner(pServ->pExecutor) == self)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SCStore *SCSave(SConnection *pCon, SCStore *oldStore) {
|
|
commandContext cc;
|
|
|
|
if (oldStore == NULL) {
|
|
oldStore = calloc(1,sizeof(*oldStore));
|
|
assert(oldStore);
|
|
}
|
|
oldStore->pCon = pCon;
|
|
if (pCon) {
|
|
oldStore->ident = pCon->ident;
|
|
oldStore->inMacro = pCon->iMacro;
|
|
oldStore->cc = SCGetContext(pCon);
|
|
oldStore->pushLevel = 0;
|
|
}
|
|
return oldStore;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SConnection *SCLoad(SCStore *conStore) {
|
|
SConnection *pCon = NULL;
|
|
commandContext old;
|
|
|
|
if (conStore) {
|
|
pCon = conStore->pCon;
|
|
}
|
|
if (pCon) {
|
|
if (conStore->ident != pCon->ident) {
|
|
conStore->pCon = NULL; /* connection is dead */
|
|
pCon = NULL;
|
|
}
|
|
}
|
|
if (pCon) {
|
|
return pCon;
|
|
}
|
|
return pServ->dummyCon;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
SConnection *SCStorePush(SCStore *conStore) {
|
|
SConnection *pCon;
|
|
|
|
pCon = SCLoad(conStore);
|
|
if (conStore->pushLevel == 0) {
|
|
if (conStore->inMacro) {
|
|
conStore->inMacroSave = pCon->iMacro;
|
|
pCon->iMacro = conStore->inMacro;
|
|
}
|
|
}
|
|
conStore->pushLevel++;
|
|
SCPushContext2(pCon, conStore->cc);
|
|
return pCon;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void SCStorePop(SCStore *conStore) {
|
|
SConnection *pCon;
|
|
|
|
pCon = SCLoad(conStore);
|
|
if (conStore->pushLevel > 0) {
|
|
SCPopContext(pCon);
|
|
conStore->pushLevel--;
|
|
if (conStore->pushLevel == 0) {
|
|
pCon->iMacro = conStore->inMacroSave;
|
|
}
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int SCStoreConnected(SCStore *conStore) {
|
|
return (conStore &&
|
|
conStore->pCon &&
|
|
conStore->pCon->ident == conStore->ident);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void SCStoreFree(SCStore *conStore) {
|
|
free(conStore);
|
|
}
|
|
/* --------------------------------------------------------------------------*/
|
|
long SCTagContext(SConnection *self, char *tagName)
|
|
{
|
|
commandContext a;
|
|
if(NULL==self) return -1;
|
|
|
|
a = SCGetContext(self);
|
|
strncpy(a.deviceID,tagName,SCDEVIDLEN);
|
|
/*
|
|
SCGetContext will already have advanced the stack pointer to the
|
|
last position
|
|
*/
|
|
LLDnodeDataTo(self->contextStack, &a);
|
|
return 1;
|
|
}
|
|
/* --------------------------------------------------------------------------*/
|
|
long SCAdvanceContext(SConnection *self, char *tagName)
|
|
{
|
|
if(NULL==self) return -1;
|
|
self->iCmdCtr++;
|
|
if(999999<self->iCmdCtr)
|
|
{
|
|
self->iCmdCtr = 0;
|
|
}
|
|
return SCPushContext(self, self->iCmdCtr, tagName);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SCVerifyConnection(SConnection *self)
|
|
{
|
|
return VerifyConnection(self);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void SCWriteToLogFiles(SConnection *self, char *buffer)
|
|
{
|
|
writeToLogFiles(self,buffer);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SCDoSockWrite(SConnection *self, char *buffer)
|
|
{
|
|
return doSockWrite(self,buffer);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void KillFreeConnections(void) {
|
|
SConnection *next;
|
|
while (freeConnections) {
|
|
next = freeConnections->next;
|
|
free(freeConnections);
|
|
freeConnections = next;
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SCPushContext(SConnection *self, int ID, char *deviceID)
|
|
{
|
|
commandContext neu;
|
|
|
|
if(!VerifyConnection(self))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
neu.transID = ID;
|
|
strncpy(neu.deviceID,deviceID,SCDEVIDLEN);
|
|
LLDnodeAppendFrom(self->contextStack,&neu);
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------*/
|
|
int SCPushContext2(SConnection *self, commandContext cc)
|
|
{
|
|
return SCPushContext(self,cc.transID, cc.deviceID);
|
|
}
|
|
/*------------------------------------------------------*/
|
|
commandContext SCGetContext(SConnection *pCon)
|
|
{
|
|
commandContext neu;
|
|
neu.transID = 0;
|
|
strcpy(neu.deviceID,"Undefined");
|
|
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return neu;
|
|
}
|
|
if(LLDnodePtr2Last(pCon->contextStack) == 1){
|
|
LLDnodeDataTo(pCon->contextStack, &neu);
|
|
}
|
|
return neu;
|
|
}
|
|
/*-----------------------------------------------------*/
|
|
int SCPopContext(SConnection *pCon)
|
|
{
|
|
if(!VerifyConnection(pCon))
|
|
{
|
|
return 0;
|
|
}
|
|
if(LLDnodePtr2Last(pCon->contextStack) != 0)
|
|
{
|
|
LLDnodeDelete(pCon->contextStack);
|
|
}
|
|
return 1;
|
|
}
|