/*-------------------------------------------------------------------------- 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 #include #include #include #include #include #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; } if(pVictim->inUse > 0) { 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); /* 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 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; } 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) { iRet = TelnetWrite(self->pSock,buffer); } else { iRet = NETWrite(self->pSock,buffer,strlen(buffer)); if(!HasNL(buffer)) { iRet = NETWrite(self->pSock,"\n",sizeof("\n")); } } if(!iRet) { SCnoSock(self); WriteToCommandLog("SYS> ","Connection broken on send"); } } 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) { iRet = TelnetWrite(self->pSock,buffer); } else { iRet = NETWrite(self->pSock,buffer,strlen(buffer)); if(!HasNL(buffer)) { iRet = NETWrite(self->pSock,"\n",sizeof("\n")); } } if(!iRet) { SCnoSock(self); WriteToCommandLog("SYS> ","Send broken to connection"); } } 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 = 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 */ 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; } /*-------------------------------------------------------------------------*/ 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; 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); sprintf(pFrom,"Prompted from sock %2.2d: ", pCon->pSock->sockid); WriteToCommandLog(pFrom,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; } /*--------------------------------------------------------------------------*/ 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) { if(self->inUse != 0) { return 1; } else { 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) { if(self->inUse != 0) { 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) { SCWrite(self,pPtr,eWarning); } } else if(iSignal == TOKENRELEASE) { self->iGrab = 0; } else if(iSignal == TOKENGRAB) { self->iGrab = 1; } }