From da3dfd9d76446e62dad80b1b61f561a3e50bde9f Mon Sep 17 00:00:00 2001 From: zolliker Date: Tue, 11 Apr 2006 07:26:55 +0000 Subject: [PATCH] - Introducted Arg2Tcl as a replacement for some calls to Arg2Text - Fixed a memory leak --- conman.c | 15 ++++--- emon.c | 4 +- evcontroller.c | 6 +-- macro.c | 67 ++++++++++++++----------------- protocol.c | 13 ++++-- remob.c | 18 ++++++--- script.c | 10 ++++- sicscron.c | 10 ++--- splitter.c | 105 +++++++++++++++++++++++++++++++++++++++---------- splitter.h | 15 +++++++ tclintimpl.c | 13 +++--- 11 files changed, 184 insertions(+), 92 deletions(-) diff --git a/conman.c b/conman.c index d3dbe7d7..26d92edd 100644 --- a/conman.c +++ b/conman.c @@ -132,7 +132,10 @@ extern pServer pServ; } do - { /* loop until an unused ident is found */ + { /* loop until an unused ident is found. This test needed only for + the case there some object has already the name con. + 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! */ @@ -1721,7 +1724,8 @@ static void writeToLogFiles(SConnection *self, char *buffer) Item sItem; pCBAction pCB = NULL; CommandList *pCom = NULL; - int iMacro; + int iMacro; + char *script; self = (SConnection *)pData; if(!VerifyConnection(self)) @@ -1781,17 +1785,18 @@ static void writeToLogFiles(SConnection *self, char *buffer) return 0; } + script = Arg2Tcl(argc-4, &argv[4], NULL, 0); + /* now we can install the callback */ pCB = (pCBAction)malloc(sizeof(CBAction)); - if(!pCB) + if(!pCB || !script) { 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); + pCB->pAction = script; sItem.pInterface = pInterface; sItem.lID = RegisterCallback(pInterface, SCGetContext(pCB->pCon), iEvent, ConCallBack, pCB, CBKill); diff --git a/emon.c b/emon.c index e158510c..554c90d6 100644 --- a/emon.c +++ b/emon.c @@ -85,8 +85,7 @@ /* remove all the names */ -/* - iRet == LLDnodePtr2First(self->iList); + iRet = LLDnodePtr2First(self->iList); while(iRet != 0) { LLDnodeDataTo(self->iList,&sEntry); @@ -97,7 +96,6 @@ } iRet = LLDnodePtr2Next(self->iList); } -*/ /* remove list */ LLDdelete(self->iList); diff --git a/evcontroller.c b/evcontroller.c index e0ad2a23..991dcde4 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -1214,12 +1214,11 @@ static void ErrReport(pEVControl self) strtolower(argv[1]); if(strcmp(argv[1],"errorscript") == 0) { - Arg2Text(argc-2,&argv[2],pBueffel,255); if(self->errorScript != NULL) { free(self->errorScript); } - self->errorScript = strdup(pBueffel); + self->errorScript = Arg2Tcl(argc-2,&argv[2],NULL,0); SCSendOK(pCon); SCparChange(pCon); return 1; @@ -1542,8 +1541,7 @@ int RemoveEVController(SConnection *pCon, char *name) { return 0; } if (pNew->pDriv->SavePars) { - Arg2Text(argc-3, argv+3, pBueffel, sizeof pBueffel); - pNew->creationArgs = strdup(pBueffel); + pNew->creationArgs = Arg2Tcl(argc-3, argv+3, NULL, 0); pNew->pDes->SaveStatus = EVSaveStatus; } else { pNew->creationArgs = NULL; diff --git a/macro.c b/macro.c index 77358a13..2fdb4f36 100644 --- a/macro.c +++ b/macro.c @@ -174,14 +174,14 @@ return TCL_ERROR; } } - pSics->lastUnknown[pSics->iStack] = strdup(comBuffer); + if (pSics->lastUnknown[pSics->iStack]) free(pSics->lastUnknown[pSics->iStack]); + pSics->lastUnknown[pSics->iStack] = strdup(comBuffer); /* invoke */ iMacro = SCinMacro(pCon); SCsetMacro(pCon,1); iRet = pCommand->OFunc(pCon,pSinter,pCommand->pData,margc, myarg); SCsetMacro(pCon,iMacro); - /* lastUnkown gets deeply stacked with each SICS command exec'd. This is not reflected in code. However, lastUnknown has already @@ -844,6 +844,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { char pBueffel[1024]; + char *pCommand; pPubTcl self = NULL; int iRet, length; char *pPtr; @@ -864,45 +865,32 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, } /* make a string */ - Arg2Text(argc,argv,pBueffel,1023); - - - iRet = Tcl_Eval(pTcl,pBueffel); + pCommand = Arg2Tcl(argc,argv,pBueffel,sizeof(pBueffel)); + if (!pCommand) { + SCWrite(pCon, "ERROR: no more memory", eError); + return 0; + } + iRet = Tcl_Eval(pTcl,pCommand); + if (pCommand != pBueffel) free(pCommand); if(iRet == TCL_OK) - { length = strlen(pTcl->result); - if(length < 1024){ - strncpy(pBueffel,pTcl->result,1023); - SCWrite(pCon,pBueffel,eStatus); - } else { - length += 10; - pPtr = (char *)malloc(length*sizeof(char)); - if(pPtr == NULL){ - SCWrite(pCon, - "ERROR: out of memory in TclAction", - eError); - return 0; - } - memset(pPtr,0,length*sizeof(char)); - strncpy(pPtr,pTcl->result,length-1); - SCWrite(pCon,pPtr,eStatus); - free(pPtr); - } + { + /* we do not now why, but at some time it was found that + we need a copy, and can not use pTcl->result directly + + SCWrite(pCon,pTcl->result,eStatus); + + let us use SCPrintf, which maked always a copy + */ + SCPrintf(pCon, eStatus, "%s", pTcl->result); return 1; } else { - if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) == NULL) - { - pPtr = strdup(pTcl->result); - SCWrite(pCon,pPtr,eError); - free(pPtr); - } - else + if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) != NULL) { Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY); - strncpy(pBueffel,pTcl->result,1023); - SCWrite(pCon,pBueffel,eError); } + SCPrintf(pCon,eError,"%s",pTcl->result); return 0; } return 1; /* not reached */ @@ -990,16 +978,21 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { - char pCommand[1024], pStart[1024]; + char pBuffer[1024]; + char *pCommand; int iRet; - Arg2Text(argc-1,&argv[1],pCommand,1023); + pCommand = Arg2Tcl(argc-1,&argv[1],pBuffer, sizeof(pBuffer)); + if (!pCommand) { + SCWrite(pCon,"ERROR: no memory", eError); + return 0; + } strtolower(argv[0]); if(strcmp(argv[0],"fulltransact") == 0){ - snprintf(pStart,1023,"TRANSACTIONSTART %s",pCommand); - SCWrite(pCon,pStart,eError); + SCPrintf(pCon,eError, "TRANSACTIONSTART %s",pCommand); } iRet = InterpExecute(pSics,pCon,pCommand); + if (pCommand != pBuffer) free(pCommand); SCWrite(pCon,"TRANSACTIONFINISHED",eError); return iRet; } diff --git a/protocol.c b/protocol.c index 793a9fe9..3a02fc21 100644 --- a/protocol.c +++ b/protocol.c @@ -171,7 +171,8 @@ void DeleteProtocol(void *self) static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ commandContext comCon; - char command[1024]; + char buffer[1024]; + char *command; int status; if(argc < 3){ @@ -186,11 +187,15 @@ static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } strncpy(comCon.deviceID,argv[2],SCDEVIDLEN); - memset(command,0,1024*sizeof(char)); - Arg2Text(argc-2,&argv[2],command,1023); - + memset(buffer,0,sizeof(buffer)); + command = Arg2Tcl(argc-2,&argv[2],buffer,sizeof buffer); + if (!command) { + SCWrite(pCon,"ERROR: no more memory",eError); + return 0; + } SCPushContext2(pCon,comCon); status = InterpExecute(pSics,pCon,command); + if (command != buffer) free(command); SCPopContext(pCon); return status; } diff --git a/remob.c b/remob.c index 06531426..217a2675 100644 --- a/remob.c +++ b/remob.c @@ -534,7 +534,11 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, float fValue; long lID; char *endp; + char *argv0; + char *cmd; + /* char acce[128], inte[128]; + */ int rights; RemChannel *rc; @@ -550,16 +554,19 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, if (argc == 1) { iRet = RemTransact(remserver, rc, pCon, argv[0], ">", NULL); } else if (strcasecmp(argv[1],"list") == 0) { - snprintf(buf, sizeof(buf), "%s ", remob->name); - i = strlen(buf); - Arg2Text(argc-1, argv+1, buf + i, sizeof buf - i); /* snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name); snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name); */ - RemTransact(remserver, rc, pCon, buf, ">", NULL); - + argv0 = argv[0]; + argv[0] = remob->name; + cmd = Arg2Tcl(argc, argv, buf, sizeof buf); + argv[0] = argv0; + if (cmd) { + RemTransact(remserver, rc, pCon, cmd, ">", NULL); + if (cmd != buf) free(cmd); + } iRet=1; } else { pos=snprintf(buf, sizeof(buf), "%s ", remob->name); @@ -620,7 +627,6 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, float fValue; long lID; char *endp, *serverport, *thishostname; - char acce[128], inte[128]; struct sockaddr_in adr; struct hostent *thishost; Remob *p, *next; diff --git a/script.c b/script.c index 3dfa8e46..a539ca7c 100644 --- a/script.c +++ b/script.c @@ -411,6 +411,7 @@ char pBueffel[256]; Tcl_Interp *pTcl = NULL; int iRet; + char *cmd; assert(pCon); assert(pSics); @@ -425,8 +426,13 @@ pTcl = InterpGetTcl(pSics); assert(pTcl); - Arg2Text(argc-1,&argv[1],pBueffel,255); - iRet = Tcl_Eval(pTcl,pBueffel); + cmd = Arg2Tcl(argc-1,&argv[1],pBueffel,sizeof pBueffel); + if (!cmd) { + SCWrite(pCon,"ERROR: no more memory",eError); + return 0; + } + iRet = Tcl_Eval(pTcl,cmd); + if (cmd != pBueffel) free(cmd); if(strlen(pTcl->result) > 1) { SCWrite(pCon,pTcl->result,eValue); diff --git a/sicscron.c b/sicscron.c index 8198b2d4..ce49d5d2 100644 --- a/sicscron.c +++ b/sicscron.c @@ -83,8 +83,8 @@ { pCron pNew = NULL; int iVal, iRet; - char pBueffel[512]; - + char *cmd; + /* only managers may do this */ if(!SCMatchRights(pCon,usMugger)) { @@ -108,11 +108,11 @@ } /* concatenate the rest to the command */ - Arg2Text(argc-2,&argv[2],pBueffel,511); + cmd = Arg2Tcl(argc-2,&argv[2],NULL,0); /* create data structure and install task */ pNew = (pCron)malloc(sizeof(Cron)); - if(!pNew) + if(!pNew || !cmd) { SCWrite(pCon,"ERROR: out of memory in sicscron",eError); return 0; @@ -124,7 +124,7 @@ return 0; } pNew->iIntervall = iVal; - pNew->pCommand = strdup(pBueffel); + pNew->pCommand = cmd; pNew->tNext = 0; pNew->iEnd = 1; diff --git a/splitter.c b/splitter.c index 4fc9a9d2..7d67de02 100644 --- a/splitter.c +++ b/splitter.c @@ -11,6 +11,7 @@ #include #include #include +#include "tcl.h" #include "splitter.h" typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; @@ -116,7 +117,7 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; char pBueffel[132]; char *pChar; CharType eWhat; - int i; + int i, n; if(!pLine)return NULL; @@ -142,9 +143,14 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; pChar++; while( (isEnd(*pChar) != 2) && (CheckSpecial(pChar) != eQuote)) { - pBueffel[i] = *pChar; + if (*pChar == '\\') { + pBueffel[i] = Tcl_Backslash(pChar, &n); + pChar += n; + } else { + pBueffel[i] = *pChar; + pChar++; + } i++; - pChar++; } pBueffel[i] = '\0'; pChar++; @@ -226,17 +232,14 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; /* loop through arguments */ for( i = 0; i < argc; i++) { - /* figure out what we have */ - for(ii = 0; ii < strlen(argv[i]); ii++) - { - eWhat = CheckSpecial(argv[i]); - - /* skip whitespace */ - if(eWhat == eSpace) + /* figure out what we have */ + for(ii = 0; ii < strlen(argv[i]); ii++) { - continue; - } + eWhat = CheckSpecial(argv[i]); + /* skip whitespace */ + if(eWhat != eSpace) break; + } /* Create Token */ if(pList == NULL) { @@ -253,13 +256,6 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; /* copy text always */ pCurrent->text = strdup(argv[i]); - /* text */ - if(eWhat == eeText) - { - pCurrent->Type = eText; - break; - } - /* numbers */ if(eWhat == eNum) { @@ -275,9 +271,11 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; pCurrent->Type = eFloat; sscanf(argv[i],"%f",&(pCurrent->fVal)); } - break; } - } + else + { /* all else is text */ + pCurrent->Type = eText; + } } return pList; } @@ -401,6 +399,71 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; } return 1; } +/*--------------------------------------------------------------------------*/ +char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) { + int i, l, firstArgToQuote, quote; + char ch; + char *res, *arg; + + l = 0; + firstArgToQuote = argc; + quote = 0; + for (i=0; i buffersize) { + buffer = calloc(l,1); + if (buffer == NULL) return NULL; + } + res = buffer; + for (i=0; i= firstArgToQuote) *res++ = '"'; + arg = argv[i]; + ch = *arg++; + while (ch != '\0') { + switch (ch) { + case '"': *res++ = '\\'; *res++ = '"'; break; + case '\\': *res++ = '\\'; *res++ = '\\'; break; + case '\r': *res++ = '\\'; *res++ = 'r'; break; + case '\n': *res++ = '\\'; *res++ = 'n'; break; + default: *res++ = ch; break; + } + ch = *arg++; + } + if (i >= firstArgToQuote) *res++ = '"'; + *res++ = ' '; + } + if (res > buffer) res--; /* remove trailing space */ + *res='\0'; + return buffer; +} /*============================================================================ Testprogram, can be activated by defining MAIN diff --git a/splitter.h b/splitter.h index 536a7f4d..a5e6fbbf 100644 --- a/splitter.h +++ b/splitter.h @@ -73,4 +73,19 @@ typedef struct _TokenEntry { /*! isNumeric test if pText is a number !*/ + char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize); + /*! + Arg2Tcl converts an argc, argv[] pair into a line of + text. Args are quoted if needed, in order to be interpreted as + proper tcl command. If buffer is NULL or the result longer than + buffersize, the result is allocated by Arg2Tcl. + If the results fits the buffer, buffer is returned. + If no memory is available or any element of argv is NULL, NULL is + returned. + The result has to be freed by the caller after use be something like: + + if (result != NULL && result != buffer) free(result); + + !*/ + #endif diff --git a/tclintimpl.c b/tclintimpl.c index c94d54d6..f64bf7b1 100644 --- a/tclintimpl.c +++ b/tclintimpl.c @@ -135,7 +135,7 @@ int TclIntAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pTclInt self = NULL; char pBuffer[1024]; - + char *cmd; self = (pTclInt)pData; assert(self); @@ -159,11 +159,14 @@ int TclIntAction(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"backup") == 0){ - Arg2Text(argc-2, &argv[2],pBuffer,1023); - if(self->fd != NULL){ - fprintf(self->fd,"%s\n",pBuffer); + cmd = Arg2Tcl(argc-2, &argv[2],pBuffer,1023); + if (cmd) { + if(self->fd != NULL){ + fprintf(self->fd,"%s\n",pBuffer); + } + if (cmd != pBuffer) free(cmd); + SCSendOK(pCon); } - SCSendOK(pCon); return 1; } else { sprintf(pBuffer,"ERROR: keyword %s to %s not recognized",