diff --git a/SCinter.c b/SCinter.c index 98ab7358..8b8138c6 100644 --- a/SCinter.c +++ b/SCinter.c @@ -62,9 +62,6 @@ #include "definealias.h" -#define MAXLEN 256 -#define MAXPAR 100 - /*--------------------------------------------------------------------------*/ SicsInterp *InitInterp(void) { @@ -91,10 +88,11 @@ return pInter; } /*------------------------------------------------------------------------*/ - int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, - KillFunc pKFunc, void *pData) + int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, + KillFunc pKFunc, void *pData, int startupOnly) { CommandList *pNew = NULL; + CommandList *p, *tail; char pBueffel[512]; assert(pName); @@ -134,19 +132,42 @@ pNew->OFunc = pFunc; pNew->KFunc = pKFunc; pNew->pData = pData; - pNew->pNext = pInterp->pCList; + pNew->pNext = NULL; + pNew->startupOnly = startupOnly; - - if(pInterp->pCList) + /* find end of list */ + tail = NULL; + p = pInterp->pCList; + while(p != NULL) { - pInterp->pCList->pPrevious = pNew; + tail = p; + p = p->pNext; } - pNew->pPrevious = NULL; + if (tail==NULL) { /* first entry */ + pInterp->pCList = pNew; + } else { /* insert at tail */ + tail->pNext = pNew; + } + pNew->pPrevious = tail; - /* update headpointer */ - pInterp->pCList = pNew; return 1; } +/*------------------------------------------------------------------------*/ + int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, + KillFunc pKFunc, void *pData) + { + return AddCommandWithFlag(pInterp, pName, pFunc, pKFunc, pData, 0); + } +/*------------------------------------------------------------------------*/ + int AddIniCmd(char *pName, ObjectFunc pFunc) + { + return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 1); + } +/*------------------------------------------------------------------------*/ + int AddCmd(char *pName, ObjectFunc pFunc) + { + return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 0); + } /*------------------------------------------------------------------------*/ int RemoveCommand(SicsInterp *pInterp, char *pName) { @@ -198,10 +219,21 @@ return 1; } -#define MAXLEN 256 -#define MAXCOM 50 -extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk); -extern char *SkipSpace(char *pPtr); + +/*------------------------------------------------------------------------*/ + void RemoveStartupCommands(void) + { + CommandList *pCurrent, *pNext; + pCurrent = pServ->pSics->pCList; + while(pCurrent) + { + pNext = pCurrent->pNext; + if (pCurrent->startupOnly) { + RemoveCommand(pServ->pSics, pCurrent->pName); + } + pCurrent = pNext; + } + } /*------------------------------------------------------------------------*/ int InterpExecute(SicsInterp *self,SConnection *pCon, char *pText) { @@ -233,18 +265,21 @@ extern char *SkipSpace(char *pPtr); /* convert to argc, argv */ argc = 0; + argv = NULL; Text2Arg(pText,&argc,&argv); /* the first one must be the target object. If not given an empty command string was given which will be silently ignored */ if(argc < 1) { - return 1; + iRet = 1; + goto deleteArgv; } if(argv[0] == NULL) { - SCWrite(pCon,"ERROR: failed to parse command",eError); - return -1; + SCWrite(pCon,"ERROR: failed to parse command",eError); + iRet = -1; + goto deleteArgv; } /* find it */ @@ -254,8 +289,8 @@ extern char *SkipSpace(char *pPtr); sprintf(pBueffel,"ERROR: Object -> %s <- NOT found", argv[0]); SCWrite(pCon,pBueffel,eError); - return -1; - + iRet = -1; + goto deleteArgv; } @@ -266,16 +301,18 @@ extern char *SkipSpace(char *pPtr); iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv); MacroPop(); - /* delete argv */ - for(i = 0; i < argc; i++) - { - if(argv[i] != NULL) - { - free(argv[i]); - } + deleteArgv: + if (argv) { + /* delete argv */ + for(i = 0; i < argc; i++) + { + if(argv[i] != NULL) + { + free(argv[i]); + } + } + free(argv); } - free(argv); - return iRet; } /*------------------------------------------------------------------------*/ @@ -319,23 +356,24 @@ extern char *SkipSpace(char *pPtr); float fVal; pIDrivable pDriv = NULL; void *pTest = NULL; - + char tmpfile[PATH_MAX]; + int l; + assert(self); assert(file); - /* open file */ - fd = fopen(file,"w"); - if(!fd) - { + /* make sure that status file is always valid M.Z. Apr 2005 */ + /* create a temporary file first */ + l=strlen(file); + if (l >= sizeof tmpfile - 2) { return 0; } - /* remove it, as I found garbage from previous runs in the - status file - */ - fclose(fd); - remove(file); + strcpy(tmpfile, file); + tmpfile[l]='.'; + tmpfile[l+1]='\0'; + remove(tmpfile); /* remove already existing file */ - fd = fopen(file,"w"); + fd = fopen(tmpfile,"w"); if(!fd) { return 0; @@ -376,11 +414,15 @@ extern char *SkipSpace(char *pPtr); } pCurrent = pCurrent->pNext; } + fclose(fd); + /* rename temporary to final file (this is an atomic action) */ + if (0 > rename(tmpfile, file)) { + return 0; + } if(iMot) { fprintf(fd,"Success \n"); } - fclose(fd); return 1; } /*------------------------------------------------------------------------*/ @@ -426,7 +468,10 @@ extern char *SkipSpace(char *pPtr); memory problem deep in the Tcl library. This causes a core dump on each SICS restart and breaks the use of external tools. Tcl_DeleteInterp(pTcl); + + call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05 */ + KillSicsUnknown(); } free(self); diff --git a/SCinter.h b/SCinter.h index 34e96501..3d759c22 100644 --- a/SCinter.h +++ b/SCinter.h @@ -30,6 +30,7 @@ typedef struct __Clist { void *pData; struct __Clist *pNext; struct __Clist *pPrevious; + int startupOnly; } CommandList; typedef struct __SINTER @@ -63,6 +64,12 @@ typedef struct __SINTER int RemoveCommand(SicsInterp *pInterp, char *pName); /* kills the command name from the interpreter pInterp */ +/*-------------------------------------------------------------------------*/ + int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, + KillFunc pKFunc, void *pData, int startupFlag); + int AddIniCmd(char *pName, ObjectFunc pFunc); /* command will be deleted after startup */ + int AddCmd(char *pName, ObjectFunc pFunc); /* syntactic sugar for AddCommand without data */ + void RemoveStartupCommands(void); /* called after startup to delete startup commands */ /*-------------------------------------------------------------------------*/ int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand);