diff --git a/SCinter.c b/SCinter.c index 9b14e78c..ac5d32e6 100644 --- a/SCinter.c +++ b/SCinter.c @@ -33,7 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR diff --git a/callback.c b/callback.c index e1c59d30..a407fb5f 100644 --- a/callback.c +++ b/callback.c @@ -47,11 +47,10 @@ #include "lld.h" #include "sics.h" #include "macro.h" - +#include "splitter.h" #define CALLBACK 17777 - /*--------------------- The interface datastructure ---------------------*/ typedef struct __ICallBack { int iID; @@ -262,16 +261,21 @@ static int ScriptCallback(int iEvent, void *pEventData, void *pUserData) fprintf(stdout,"ERROR: ScriptCallback: no script to execute\n"); return 0; } + /* SCSetWriteFunc(pCon,CallbackWrite); MacroPush(pCon); pTcl = InterpGetTcl(pServ->pSics); - status = Tcl_GlobalEval(pTcl,(char *)pUserData); + status = Tcl_Eval(pTcl,(char *)pUserData); if(status != TCL_OK) { fprintf(stdout,"ERROR: in CallbackScript: %s\n",(char *)pUserData); fprintf(stdout,"Tcl-error: %s\n",pTcl->result); } MacroPop(); + */ + SCSetRights(pCon,usInternal); + status = InterpExecute(pServ->pSics,pCon,(char *)pUserData); + SCDeleteConnection(pCon); return 1; } @@ -302,7 +306,7 @@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, strtolower(argv[1]); if(strcmp(argv[1],"connect") == 0) { - if(argc < 5) + if(argc < 4) { SCWrite(pCon,"ERROR: not enough arguments to CallbackScript connect", eError); @@ -327,8 +331,9 @@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, SCWrite(pCon,"ERROR: event type not known",eError); return 0; } + Arg2Text(argc-4,&argv[4],pBuffer,131); lID = RegisterCallback(pCall,iEvent,ScriptCallback, - strdup(argv[4]),free); + strdup(pBuffer),free); sprintf(pBuffer,"callback = %ld", lID); SCWrite(pCon,pBuffer,eValue); return 1; diff --git a/conman.c b/conman.c index 9873e748..28015567 100644 --- a/conman.c +++ b/conman.c @@ -25,6 +25,11 @@ Added simulation mode Mark Koennecke, March 2003 + Refactored a bit, removed SCWriteBinary (never used anywhere), added + appending outcode to text, + Mark Koennecke, July 2004 + + Copyright: see copyright.h -----------------------------------------------------------------------------*/ #include "fortify.h" @@ -55,6 +60,9 @@ extern pServer pServ; +#include "outcode.c" /* text for OutCode */ + + /*------ Max Size of Command Stack */ #define MAXSTACK 100 /*---------- Magic ID Header */ @@ -374,7 +382,7 @@ extern pServer pServ; return; } - if(pVictim->inUse > 0) + if(SCActive(pVictim)) { SCnoSock(pVictim); if(pVictim->pSock) @@ -573,6 +581,54 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) } 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",sizeof("\n")); + } + } + if(!iRet) + { + SCnoSock(self); + WriteToCommandLog("SYS> ","Connection broken on send"); + } + } + 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]); + } + } + } +} /*--------------------------------------------------------------------------*/ static int SCNormalWrite(SConnection *self, char *buffer, int iOut) { @@ -611,30 +667,7 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) /* 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); - } + iRet = doSockWrite(self,buffer); } } else /* not in interpreter, normal logic */ @@ -644,45 +677,94 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) return 0; /* first the socket */ + iRet = doSockWrite(self,buffer); + + writeToLogFiles(self,buffer); + } + return 1; + } +/*--------------------------------------------------------------------------*/ + static int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut) + { + int i, iPtr, iRet, length; + char pBueffel[80]; + char *bufPtr = NULL; + + if(!VerifyConnection(self)) + { + return 0; + } + + /* log it for any case */ 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); - WriteToCommandLog("SYS> ","Send broken to connection"); - } + { + iRet = self->pSock->sockid; } else { - printf("%s \n",buffer); - } + 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); + } - /* now all the possible logfiles */ - for(i = 0; i < self->iFiles; i++) + /* + 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(self->pSics,buffer); + /* print it to client if error message */ + if((iOut== eError) || (iOut == eWarning) ) { - if(self->pFiles[i]) - { - fputs(buffer,self->pFiles[i]); - if(! HasNL(buffer)) - { - fputs("\n",self->pFiles[i]); - fflush(self->pFiles[i]); - } - } + 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; } /*--------------------------------------------------------------------------*/ @@ -721,31 +803,8 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) return 0; /* 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); - } - } + iRet = doSockWrite(self,buffer); + } return 1; } /*--------------------------------------------------------------------------*/ @@ -810,20 +869,8 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) /* 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]); - } - } - } + + writeToLogFiles(self,buffer); } return 1; } @@ -836,67 +883,6 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) } 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) @@ -1205,6 +1191,7 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) char *pPtr = NULL; char pFrom[50]; Status eOld; + int oldMode; if(!VerifyConnection(pCon)) { @@ -1217,8 +1204,16 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) CostaUnlock(pCon->pStack); while(1) { - /* wait a second */ + /* + 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) { @@ -1366,8 +1361,8 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) 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 */ + config output normal | withcode Sets output mode +---------------------------------------------------------------------------*/ int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -1472,6 +1467,25 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) 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 + { + SCWrite(pCon,"ERROT: output mode not recognised",eError); + return 0; + } + SCSendOK(pCon); + return 1; + } else if(strcmp(argv[1],"rights") == 0) { if(argc < 4) @@ -1697,7 +1711,7 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) if(self->iEnd) { - if(self->inUse != 0) + if(SCActive(self)) { return 1; } @@ -1768,7 +1782,7 @@ void SCSetWriteFunc(SConnection *self, writeFunc x) if(self->iEnd) { - if(self->inUse != 0) + if(SCActive(self)) { return 1; } @@ -1828,3 +1842,16 @@ void SCparChange(SConnection *self) } self->parameterChange = 1; } +/*------------------------------------------------------------------------*/ +int SCActive(SConnection *self) +{ + if(self->inUse != 0 ) + { + return 1; + } + if(GetExeOwner(pServ->pExecutor) == self) + { + return 1; + } + return 0; +} diff --git a/conman.h b/conman.h index 6e4ff90e..9d230daa 100644 --- a/conman.h +++ b/conman.h @@ -115,6 +115,7 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int SCMatchRights(SConnection *pCon, int iCode); int SCGetOutClass(SConnection *self); int SCGetGrab(SConnection *pCon); + int SCActive(SConnection *pCon); /********************* simulation mode ************************************/ void SCSetSimMode(SConnection *pCon, int value); int SCinSimMode(SConnection *pCon); diff --git a/devexec.c b/devexec.c index fb0ff45c..761da681 100644 --- a/devexec.c +++ b/devexec.c @@ -497,6 +497,7 @@ #ifdef DEBUG printf("Wait4Success finished\n"); #endif + self->iRun = 0; return self->iStatus; } /*--------------------------------------------------------------------------*/ diff --git a/devexec.h b/devexec.h index 9dae95a5..1382a460 100644 --- a/devexec.h +++ b/devexec.h @@ -1,4 +1,4 @@ - + #line 195 "devexec.w" /*---------------------------------------------------------------------------- diff --git a/evcontroller.c b/evcontroller.c index 52bf3a8f..939cdc7f 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -365,9 +365,13 @@ static void ErrReport(pEVControl self) char pBueffel[256]; self->pDriv->GetValues(self->pDriv,&self->fTarget,&fPos,&fDelta); - sprintf(pBueffel,"WARNING: %s is out of range by %g",self->pName,fDelta); - ErrWrite(pBueffel); - self->iWarned = 1; + if(self->iWarned == 0) + { + sprintf(pBueffel,"WARNING: %s is out of range by %g", + self->pName,fDelta); + ErrWrite(pBueffel); + self->iWarned = 1; + } } /*-------------------------------------------------------------------------*/ static int ErrLazy(void *pData) @@ -408,6 +412,7 @@ static void ErrReport(pEVControl self) /* OK now, continue */ SetStatus(eEager); + self->iWarned = 0; ContinueExecution(pExe); return 1; } @@ -444,6 +449,7 @@ static void ErrReport(pEVControl self) returns */ self->eMode = EVMonitor; + self->iWarned = 0; } else { @@ -467,6 +473,7 @@ static void ErrReport(pEVControl self) /* interrupt */ SetInterrupt((int)ObVal(self->pParam,INTERRUPT)); + self->iWarned = 0; return 1; } /*---------------------------------------------------------------------------*/ @@ -482,6 +489,7 @@ static void ErrReport(pEVControl self) ErrWrite("Running to safe value"); self->pDriv->SetValue(self->pDriv, ObVal(self->pParam,SAFEVALUE)); self->eMode = EVIdle; + self->iWarned = 0; return 1; } /*---------------------------------------------------------------------------*/ @@ -1088,10 +1096,6 @@ static void ErrReport(pEVControl self) } iRet = VarlogWrapper(self->pLog,pCon, argv[2],argv[3],argv[0]); - if(iRet) - { - SCSendOK(pCon); - } return iRet; } else if( argc < 3) /* either parameter or drive */ diff --git a/fomerge.c b/fomerge.c index 3556d0da..2a9c1e64 100644 --- a/fomerge.c +++ b/fomerge.c @@ -30,11 +30,6 @@ static pFit fitter = NULL; -/* change this in line with HistMem.h */ - -/* typedef int HistInt; */ -/* commented out by M.Z. (already defined in HistMem.h, g77 complains) */ - #include "fomerge.h" @@ -562,9 +557,10 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon, pNXScript pNexus, char *alias, float fElastic) { - int status, iTime, iDet; + int status, iTime, iDet, i; const float *fTimeBin = NULL; int *sum = NULL; + long *lSum = NULL; pHistMem pMem = NULL; float fCenter, fFWHM, fStdDev, fVal; @@ -594,7 +590,22 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon, return NX_ERROR; } } - status = CalculateFitFromData(fitter,fTimeBin,sum,iTime); + /* + copy sum to make compiler happy + */ + lSum = (long *)malloc(iDet*sizeof(long)); + if(lSum == NULL) + { + SCWrite(pCon,"ERROR: out of memory in putElastc",eError); + free(sum); + return NX_ERROR; + } + for(i = 0; i < iDet; i++) + { + lSum[i] = sum[i]; + } + status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime); + free(lSum); if(status != 1) { SCWrite(pCon,"WARNING: problem locating elastic peak",eWarning); diff --git a/help.c b/help.c index daf44b15..6db7c9c9 100644 --- a/help.c +++ b/help.c @@ -25,10 +25,6 @@ void KillHelp(void *pData){ free(helpDirs); helpDirs = NULL; } - if(defaultFile != NULL){ - free(defaultFile); - defaultFile = NULL; - } } /*-----------------------------------------------------------------------*/ static FILE *findHelpFile(char *name){ diff --git a/hkl.c b/hkl.c index e798dca8..5144cf61 100644 --- a/hkl.c +++ b/hkl.c @@ -495,7 +495,7 @@ static int chiVertical(double chi){ static int tryOmegaTweak(pHKL self, MATRIX z1, double *stt, double *om, double *chi, double *phi){ int status; - float fLower, fUpper, omTarget, omOffset; + float fLower, fUpper, omTarget, omOffset, phiSign; double dumstt, offom, offchi, offphi; @@ -535,7 +535,8 @@ static int tryOmegaTweak(pHKL self, MATRIX z1, double *stt, double *om, dumstt = *stt; offom = omTarget; offchi = *chi; - offphi = *phi - omOffset; + MotorGetPar(self->pPhi,"sign",&phiSign); + offphi = *phi - omOffset*phiSign; if(checkBisecting(self,&dumstt,offom,offchi,offphi)){ *om = offom; *chi = offchi; @@ -827,7 +828,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, } /* some people are stupid.......... */ - myPsi = circlify(myPsi); + myPsi = circlify(fPsi); /* no retries if specific psi requested. @@ -861,9 +862,19 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, if(!status) { - sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f", + if(iRetry == 1) + { + sprintf(pBueffel, + "ERROR: cannot calculate %4.1f %4.1f %4.1f, psi = %4.1f", + fHKL[0], fHKL[1], fHKL[2], fPsi); + SCWrite(pCon,pBueffel,eError); + } + else + { + sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f", fHKL[0], fHKL[1], fHKL[2]); - SCWrite(pCon,pBueffel,eError); + SCWrite(pCon,pBueffel,eError); + } } mat_free(z1); @@ -1082,8 +1093,17 @@ ente: return 0; break; case DEVDONE: - sprintf(pBueffel,"Driving to %8.4f %8.4f %8.4f done", - fHKL[0], fHKL[1], fHKL[2]); + if(fPsi > .01) + { + snprintf(pBueffel,131, + "Driving to %8.4f %8.4f %8.4f, psi = %8.4f done", + fHKL[0], fHKL[1], fHKL[2],fPsi); + } + else + { + snprintf(pBueffel,131,"Driving to %8.4f %8.4f %8.4f done", + fHKL[0], fHKL[1], fHKL[2]); + } SCWrite(pCon,pBueffel,eStatus); break; default: diff --git a/macro.c b/macro.c index aa6f88b5..7c6a34f5 100644 --- a/macro.c +++ b/macro.c @@ -2,7 +2,7 @@ All you need to evaluate macros with SICS. - The implmentation fo the macro stuff is complex and non intuitive. + The implmentation for the macro stuff is complex and non intuitive. This is the price to pay for adding the extremly powerful and strong Tcl-interpreter to SICS. The problem is that Tcl does not know anything about connections and our error handling. We have @@ -22,6 +22,8 @@ Mark Koennecke, December 1999 InternalFileEval added + Mark Koennecke, May 2004 + Added protected exec called sys. Copyright: @@ -68,6 +70,7 @@ #include "ifile.h" #include "Dbg.h" #include "servlog.h" +#include "stringdict.h" #define SICSERROR "005567SICS" /*---------------------------------------------------------------------------- @@ -213,6 +216,77 @@ free(pData); pUnbekannt = NULL; } +/*------------------------------------------------------------------------ + Implementation of a protected exec command + --------------------------------------------------------------------------*/ +static pStringDict allowedCommands = NULL; +/*----------------------------------------------------------------------*/ +int AllowExec(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + if(argc < 2) + { + SCWrite(pCon,"ERROR: not enough arguments to allowexec",eError); + return 0; + } + if(!SCMatchRights(pCon,usInternal)) + { + return 0; + } + if(allowedCommands == NULL) + { + allowedCommands = CreateStringDict(); + if(allowedCommands == NULL) + { + SCWrite(pCon, + "ERROR: not enough memory for list of allowed system commands", + eError); + return 0; + } + } + StringDictAddPair(allowedCommands,argv[1],"Allowed!"); + return 1; +} +/*--------------------------------------------------------------------*/ +static void KillExec(ClientData data) +{ + if(allowedCommands != NULL) + { + DeleteStringDict(allowedCommands); + allowedCommands = NULL; + } +} +/*------------------------------------------------------------------------ + This is in the Tcl sources +*/ +extern int Tcl_ExecObjCmd(ClientData data, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +/*-----------------------------------------------------------------------*/ +static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + char *test = NULL; + + if(objc < 2) + { + return Tcl_ExecObjCmd(clientData,interp,objc, objv); + } + + test = Tcl_GetStringFromObj(objv[1],NULL); + if(allowedCommands != NULL) + { + if(StringDictExists(allowedCommands,test)) + { + return Tcl_ExecObjCmd(clientData,interp,objc, objv); + } + } + + /* + if we are here, we are not allowed to invoke this command + */ + Tcl_AppendResult(interp,"System command NOT allowed!",NULL); + return TCL_ERROR; +} /*-------------------------------------------------------------------------- initialises a Tcl-Interpreter, installs SICS unknown mechanism and kills a few dangerous commands from the normal Tcl command set @@ -252,6 +326,7 @@ Tcl_DeleteCommand(pInter,"socket"); Tcl_DeleteCommand(pInter,"vwait"); Tcl_DeleteCommand(pInter,"exec"); + Tcl_CreateObjCommand(pInter,"exec",ProtectedExec,NULL,KillExec); return pInter; } @@ -377,7 +452,6 @@ { sprintf(pBueffel," Failed to open file -> %s <- ",argv[1]); SCWrite(pCon,pBueffel,eError); - /* SCSetInterrupt(pCon,eAbortBatch); */ return 0; } @@ -453,7 +527,7 @@ fclose(fp); Tcl_DStringFree(&command); SCWrite(pCon,"ERROR: batch processing interrupted",eError); - SetStatus(eOld); + SetStatus(eEager); return 0; } else @@ -549,7 +623,7 @@ int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]) { - OutCode eOut = eStatus; + OutCode eOut = eWarning; int i = 0, iCode, iLen; int iMacro; char *ppCode; @@ -617,7 +691,7 @@ eOut = eError; break; default: - eOut = eStatus; + eOut = eWarning; iCode = argc; break; } diff --git a/macro.h b/macro.h index b69e2103..2e1d6c18 100644 --- a/macro.h +++ b/macro.h @@ -37,6 +37,8 @@ int TclPublish(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]); + int AllowExec(SConnection *pCon, SicsInterp *pInter, void *pData, + int argc, char *argv[]); /* for maintaining the Connection stack at Unknown. Should only be used by SicsInterp module diff --git a/makefile_alpha b/makefile_alpha index 55befc4a..463b728f 100644 --- a/makefile_alpha +++ b/makefile_alpha @@ -22,7 +22,7 @@ EXTRA= SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ psi/tecs/libtecsl.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) \ - -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \ + -ltcl -lfor $(HDFROOT)/lib/libhdf5.a \ $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ $(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc diff --git a/mesure.c b/mesure.c index a64f8389..9c826efd 100644 --- a/mesure.c +++ b/mesure.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "fortify.h" #include "sics.h" @@ -24,6 +25,7 @@ #include "sicsvar.h" #include "evcontroller.h" #include "mesure.h" +#include "nxscript.h" extern void SNXFormatTime(char *pBueffel, int iLen); #define ANGERR 0.2 @@ -68,6 +70,7 @@ long *lCounts; /* array to store counting values */ float fPosition[4]; /* the real positions after driving */ int iCompact; /* true if compact scan ouput. */ + int psiMode; /* 1 for psi scan mode, 0 else */ } Mesure; /*--------------------------------------------------------------------------*/ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, @@ -112,7 +115,8 @@ pNew->fStep = 0.05; pNew->fPreset = 2; pNew->iMode = 0; - pNew->iCompact = 1; + pNew->iCompact = 1; + pNew->psiMode = 0; #ifdef MESSDEBUG pNew->lCounts = (long *)malloc(90*sizeof(long)); #endif @@ -269,7 +273,7 @@ pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],argv[6],pDanu); if(!pNew) { - SCWrite(pCon,"ERROR: no meory in MesureFactory",eError); + SCWrite(pCon,"ERROR: no memory in MesureFactory",eError); return 0; } @@ -348,7 +352,8 @@ return 1; } /*--------------------------------------------------------------------------*/ - int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon) + int MesureReflection(pMesure self, float fHKL[3], float fPsi, + SConnection *pCon) { int iRet, i; float fStart; @@ -358,7 +363,7 @@ assert(self); /* drive to reflection */ - iRet = DriveHKL(self->pCryst,fHKL,0.,0,pCon); + iRet = DriveHKL(self->pCryst,fHKL,fPsi,0,pCon); if(!iRet) { return iRet; @@ -375,7 +380,7 @@ check if we are really there. All this only because Jurg does not fix his rotten cradle. */ - CalculateSettings(self->pCryst,fHKL,0.,0,fSet,pCon); + CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); for(i = 0; i < 4; i++) { fDelta = fSet[i] - self->fPosition[i]; @@ -506,9 +511,11 @@ char pFilename[512], pRoot[512]; char pBueffel[1024]; char pBuff[132]; - int iYear, iNum; + int iYear, iNum, iTaus; float fVal, fUB[9]; pSicsVariable pVar = NULL; + char *pFile = NULL, *pPtr; + assert(self); assert(pCon); @@ -520,9 +527,17 @@ } /* create filename root */ - iNum = IncrementDataNumber(self->pDanu,&iYear); - sprintf(pRoot,"%s/trics%5.5d%4.4d.",self->pFileRoot,iNum,iYear); - self->pCurrentFile = strdup(pRoot); + pFile = makeFilename(pServ->pSics,pCon); + if(!pFile) + { + return 0; + } + pPtr = strrchr(pFile,(int)'.'); + pPtr++; + *pPtr = '\0'; + self->pCurrentFile = strdup(pFile); + free(pFile); + strncpy(pRoot,self->pCurrentFile,511); /* do the logfile */ strcpy(pFilename,pRoot); @@ -825,9 +840,9 @@ int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon) { FILE *fd = NULL; - char pBueffel[512], pTime[132]; + char pBueffel[512], pTime[132], pError[256]; int i, iRet; - float fHKL[3]; + float fHKL[3], fPsi = .0; assert(self); assert(pCon); @@ -859,15 +874,33 @@ } self->iCount = iSkip; + if(self->psiMode > 0){ + SCWrite(pCon,"WARNING: measuring in psi mode",eWarning); + } /* loop through space and measure! */ while(fgets(pBueffel,510,fd) != NULL) { for(i = 0; i < 3;i++) fHKL[i] = 0.; - iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]); + if(self->psiMode > 0){ + iRet = sscanf(pBueffel,"%f%f%f%f", + &fHKL[0],&fHKL[1],&fHKL[2],&fPsi); + if(iRet != 4){ + snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); + SCWrite(pCon,pError,eWarning); + continue; + } + } else { + iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]); + if(iRet != 3){ + snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); + SCWrite(pCon,pError,eWarning); + continue; + } + } self->iCount++; - iRet = MesureReflection(self,fHKL,pCon); + iRet = MesureReflection(self,fHKL,fPsi,pCon); if(iRet == 0) { if(SCGetInterrupt(pCon) >= eAbortBatch) @@ -1034,6 +1067,18 @@ } return 1; } + else if(strcmp(name,"psimode") == 0) + { + if(fVal >= 1.) + { + self->psiMode = 1; + } + else + { + self->psiMode = 0; + } + return 1; + } else { return 0; @@ -1079,6 +1124,11 @@ *fVal = self->iCompact; return 1; } + else if(strcmp(name,"psimode") == 0) + { + *fVal = self->psiMode; + return 1; + } else { return 0; @@ -1388,3 +1438,11 @@ } } } + + + + + + + + diff --git a/mesure.h b/mesure.h index 0db39095..8bcf388b 100644 --- a/mesure.h +++ b/mesure.h @@ -22,7 +22,8 @@ int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------- object functions -----------------------------------*/ - int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon); + int MesureReflection(pMesure self, float fHKL[3], float fPsi, + SConnection *pCon); int MesureGenReflection(pMesure self, float fHKL[3],float fSet[4], SConnection *pCon); int MesureStart(pMesure self, SConnection *pCon); int MesureReopen(pMesure self, char *filename, SConnection *pCon); diff --git a/mesure.tex b/mesure.tex index ae14c1b3..6b63596d 100644 --- a/mesure.tex +++ b/mesure.tex @@ -29,7 +29,8 @@ $\langle$mesureint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@/*------------------- object functions -----------------------------------*/@\\ -\mbox{}\verb@ int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon);@\\ +\mbox{}\verb@ int MesureReflection(pMesure self, float fHKL[3], float fPsi,@\\ +\mbox{}\verb@ SConnection *pCon);@\\ \mbox{}\verb@ int MesureGenReflection(pMesure self, float fHKL[3],float fSet[4], SConnection *pCon);@\\ \mbox{}\verb@ int MesureStart(pMesure self, SConnection *pCon);@\\ \mbox{}\verb@ int MesureReopen(pMesure self, char *filename, SConnection *pCon);@\\ diff --git a/mesure.w b/mesure.w index c5486292..3eb3d37d 100644 --- a/mesure.w +++ b/mesure.w @@ -24,7 +24,8 @@ The interface to this object consists of these functions: int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------- object functions -----------------------------------*/ - int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon); + int MesureReflection(pMesure self, float fHKL[3], float fPsi, + SConnection *pCon); int MesureGenReflection(pMesure self, float fHKL[3],float fSet[4], SConnection *pCon); int MesureStart(pMesure self, SConnection *pCon); int MesureReopen(pMesure self, char *filename, SConnection *pCon); diff --git a/motor.c b/motor.c index 6eb25e61..c19f0acd 100644 --- a/motor.c +++ b/motor.c @@ -266,6 +266,8 @@ static int reportAndFixError(pMotor self, SConnection *pCon) newStatus = HWFault; break; case MOTREDO: + snprintf(pBueffel,255,"WARNING: %s on %s",pError,self->name); + SCWrite(pCon,pBueffel,eWarning); newStatus = statusRunTo(self,pCon); break; case MOTOK: diff --git a/napi5.c b/napi5.c index 28ba1082..eff18942 100644 --- a/napi5.c +++ b/napi5.c @@ -1,3 +1,4 @@ + /*--------------------------------------------------------------------------- NeXus - Neutron & X-ray Common Data Format @@ -348,8 +349,8 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); H5Fget_obj_count(pFile->iFID,H5F_OBJ_ALL)); */ iRet = H5Fclose(pFile->iFID); - - /* + + /* Please leave this here, it helps debugging HDF5 resource leakages printf("HDF5 object count after close: %d\n", H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ALL)); @@ -870,7 +871,8 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); iRet = H5Dwrite (pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); if (iRet < 0) { - snprintf (pError,511, "ERROR: failure to write data"); + snprintf (pError,511, "ERROR: failure to write data to %s", + pFile->iCurrentLD); NXIReportError (NXpData, pError); return NX_ERROR; } diff --git a/network.c b/network.c index 6efb042c..3776084e 100644 --- a/network.c +++ b/network.c @@ -1,6 +1,6 @@ /*-------------------------------------------------------------------------- - Some metworking functions. This version for TCP/IP. + Some networking functions. This version for TCP/IP. @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -456,7 +457,81 @@ CreateSocketAdress( return 0; } } -/*--------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------*/ +static int findTerm(char *buffer, char *term) +{ + int i, j; + for(i = 0; i < strlen(buffer); i++) + { + for(j = 0; j < strlen(term); j++) + { + if(buffer[i] == term[j]) + { + return i; + } + } + } + return -1; +} +/*-------------------------------------------------------------------------*/ +int NETReadTillTermNew(mkChannel *self, int timeout, + char *pTerm, char *pBuffer, int iBufLen) +{ + time_t maxTime; + int bufPtr = 0, status, i, length; + char c; + + if(!VerifyChannel(self)) + { + return -1; + } + + maxTime = time(NULL) + (time_t)ceil((double)timeout/1000); + length = strlen(pTerm); + memset(pBuffer,0,iBufLen); + while(time(NULL) < maxTime) + { + /* + is data available + */ + status = NETAvailable(self,5); + if(status < 0) + { + return status; + } + if(status == 0) + { + continue; + } + status = recv(self->sockid,&c,1,0); + if(status < 0) + { + return status; + } + /* + printf("Read char %c\n",c); + */ + for(i = 0; i < length; i++) + { + if(c == pTerm[i]) + { + return 1; + } + } + if(iBufLen - bufPtr > 0) + { + pBuffer[bufPtr] = c; + bufPtr++; + } + } + return 0; /* timeout */ +} +/*-------------------------------------------------------------------------- +This old version may be removed in some stage. It has two problems: + - The timeouts are not properly obeyed + - The code may read more data the it should, i.e. bytes after the + terminator of your hearts desire. + -------------------------------------------------------------------------*/ int NETReadTillTerm(mkChannel *self, int timeout, char *pTerm, char *pBuffer, int iBufLen) { diff --git a/nread.c b/nread.c index 33ee54ba..aef16227 100644 --- a/nread.c +++ b/nread.c @@ -218,12 +218,15 @@ extern VerifyChannel(mkChannel *self); /* defined in network.c */ } } /*--------------------------------------------------------------------------*/ +#define COLLECT 0 +#define SKIPTERM 1 +/*------------------------------------------------------------------------*/ static int NetReadRead(pNetRead self, pNetItem pItem) { char *pPtr, *pEnd, *pBufEnd; char pBuffer[1024], pMuell[20]; char pBueffel[80]; - int i, iInt, iRet, iStat; + int i, iInt, iRet, iStat, state; /* read first */ memset(pBuffer,0,1024); @@ -271,42 +274,60 @@ extern VerifyChannel(mkChannel *self); /* defined in network.c */ pBufEnd = pBuffer + iRet; pPtr = pBuffer; pEnd = pBuffer; + state = COLLECT; while(pEnd < pBufEnd) { - if( (*pEnd != '\r') && (*pEnd != '\n')) + switch(state) { - pEnd++; - } - else - { - /* there is a string between pPtr and pEnd */ - *pEnd = '\0'; - /* do we have something in hold ? */ - if(strlen(pItem->pHold) > 0) - { - strcat(pItem->pHold,pPtr); - iStat = CostaTop(pItem->pCon->pStack,pItem->pHold); - if(!iStat) + case COLLECT: + if( (*pEnd != '\r') && (*pEnd != '\n')) + { + pEnd++; + } + else + { + /* there is a string between pPtr and pEnd */ + *pEnd = '\0'; + /* do we have something in hold ? */ + if(strlen(pItem->pHold) > 0) { - SCWrite(pItem->pCon,"ERROR: Busy",eError); + strcat(pItem->pHold,pPtr); + iStat = CostaTop(pItem->pCon->pStack,pItem->pHold); + if(!iStat) + { + SCWrite(pItem->pCon,"ERROR: Busy",eError); + } + pItem->pHold[0] = '\0'; } - pItem->pHold[0] = '\0'; - } - else - { - /* no, normal command */ - iStat = CostaTop(pItem->pCon->pStack,pPtr); - if(!iStat) + else { - SCWrite(pItem->pCon,"ERROR: Busy",eError); - } - } - pPtr = pEnd +1; - pEnd = pPtr; + /* no, normal command */ + iStat = CostaTop(pItem->pCon->pStack,pPtr); + if(!iStat) + { + SCWrite(pItem->pCon,"ERROR: Busy",eError); + } + } + pPtr = pEnd +1; + pEnd = pPtr; + state = SKIPTERM; + } + break; + case SKIPTERM: + if( (*pEnd != '\r') && (*pEnd != '\n')) + { + state = COLLECT; + pPtr = pEnd; + } + else + { + pEnd++; + } + break; } } /* when we are here we may still have an incomplete command pending */ - if(pEnd != pPtr) + if(pEnd != pPtr && strlen(pEnd) > 0) { strcpy(pItem->pHold,pPtr); } diff --git a/nserver.c b/nserver.c index 1e185f50..bd9b3a3e 100644 --- a/nserver.c +++ b/nserver.c @@ -275,7 +275,6 @@ NULL, pMon,1); - /* install telnet port */ InstallTelnet(); diff --git a/nxscript.c b/nxscript.c index d6dd170e..1d450d3d 100644 --- a/nxscript.c +++ b/nxscript.c @@ -109,6 +109,17 @@ char *makeFilename(SicsInterp *pSics, SConnection *pCon) { return pRes; } +/*---------------------------------------------------------------------*/ +void changeExtension(char *filename, char *newExtension){ + char *pPtr = NULL; + + pPtr = strrchr(filename,(int)'.'); + assert(pPtr != NULL); + + pPtr++; + assert(strlen(pPtr) >= strlen(newExtension)); + strcpy(pPtr,newExtension); +} /*======================== Action =======================================*/ static int handleFileOperations(SConnection *pCon, pNXScript self, int argc, char *argv[]){ @@ -560,9 +571,10 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, pNXScript self, int argc, char *argv[]){ pHistMem mem = NULL; - int status, timeLength; + int i, status, timeLength; char buffer[256], defString[512], dummy[40]; const float *timeBin; + float *timeCopy = NULL; if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning", @@ -595,10 +607,25 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, sprintf(defString,"%s -dim {%d} ",buffer,timeLength); /* - write - */ - status = NXDputdef(self->fileHandle, self->dictHandle, - defString,(void *)timeBin); + Divide the time binning when appropriate and write + */ + if(self->timeDivisor != 1){ + timeCopy = (float *)malloc(timeLength*sizeof(float)); + if(timeCopy == NULL){ + SCWrite(pCon,"ERROR: out of memory writing time binning",eError); + return; + } + for(i = 0; i < timeLength; i++){ + timeCopy[i] = timeBin[i]/self->timeDivisor; + } + status = NXDputdef(self->fileHandle, self->dictHandle, + defString,(void *)timeCopy); + free(timeCopy); + } else { + status = NXDputdef(self->fileHandle, self->dictHandle, + defString,(void *)timeBin); + } + if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write time binning"); SCWrite(pCon,buffer,eError); @@ -754,12 +781,12 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, sprintf(buffer,"ERROR: failed to convert %s to int", argv[3]); SCWrite(pCon,buffer,eError); - return 1; + return 1; } status = NXDputalias(self->fileHandle, self->dictHandle, argv[2],&iVal); if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write %f to alias %s", + sprintf(buffer,"ERROR: failed to write %d to alias %s", iVal, argv[2]); SCWrite(pCon,buffer,eError); } @@ -767,11 +794,12 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, } else if (strcmp(argv[1],"puttext") == 0){ /*====================*/ if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat", + SCWrite(pCon,"ERROR: insufficient number of arguments to puttext", eError); return 1; } Arg2Text(argc-3,&argv[3],buffer,1023); + trim(buffer); status = NXDdefget(self->dictHandle,argv[2],defString,1023); if(status != NX_OK){ sprintf(buffer,"ERROR: alias %s not found in puttext", @@ -889,8 +917,20 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, SCWrite(pCon,"ERROR: failed to create filename",eError); return 0; } + } else if(strcmp(argv[1],"divisor") == 0){ + if(argc < 3) { + SCWrite(pCon,"ERROR: no diviso found",eError); + return 1; + } + if(!SCMatchRights(pCon,usMugger)){ + return 1; + } + self->timeDivisor = atoi(argv[2]); + return 1; } + + if(handleFileOperations(pCon,self,argc,argv)){ return 1; } @@ -954,6 +994,7 @@ int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, free(self); return 0; } + self->timeDivisor = 1; /* create with with a default name if none specified diff --git a/nxscript.h b/nxscript.h index 8a6a5cc3..5acf16b0 100644 --- a/nxscript.h +++ b/nxscript.h @@ -20,11 +20,13 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); char *makeFilename(SicsInterp *pSics, SConnection *pCon); +void changeExtension(char *filename, char *newExtension); /*============== a personal data structure ============================*/ typedef struct { pObjectDescriptor pDes; NXhandle fileHandle; NXdict dictHandle; + int timeDivisor; } NXScript, *pNXScript; #endif diff --git a/nxscript.w b/nxscript.w index abed3db9..468e773c 100644 --- a/nxscript.w +++ b/nxscript.w @@ -35,7 +35,7 @@ the interface to the interpreter. Mark Koennecke, February 2003 ------------------------------------------------------------------------*/ -#ifndef NXSCRIPTo +#ifndef NXSCRIPT #define NXSCRIPT #include "napi.h" #include "nxdict.h" @@ -46,11 +46,13 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); char *makeFilename(SicsInterp *pSics, SConnection *pCon); +void changeExtension(char *filename, char *newExtension); /*============== a personal data structure ============================*/ typedef struct { pObjectDescriptor pDes; NXhandle fileHandle; NXdict dictHandle; + int timeDivisor; } NXScript, *pNXScript; #endif diff --git a/nxsupport.tcl b/nxsupport.tcl index 6ce650de..29157c01 100644 --- a/nxsupport.tcl +++ b/nxsupport.tcl @@ -32,6 +32,7 @@ proc writeFloatVar {alias var} { clientput [format "ERROR: failed to read %s, %s" $var $val] return } else { + set val [string trim $val] set ret [catch {expr $val * 1.0} val] if { $ret == 0} { nxscript putfloat $alias [expr $val * 1.0 ] @@ -40,14 +41,36 @@ proc writeFloatVar {alias var} { } } } +#========================================================================== +proc writeIntVar {alias var} { + set ret [catch {set val [SplitReply [$var]]} val] + if { $ret != 0} { + clientput [format "ERROR: failed to read %s, %s" $var $val] + return + } else { + set val [string trim $val] + set ret [catch {expr $val * 1.0} val] + if { $ret == 0} { + nxscript putint $alias [expr int($val * 1.0) ] + } else { + clientput "ERROR: bad value $val when reading $var" + } + } +} #========================================================================= proc writeTextVar {alias var} { - set ret [catch {set val [SplitReply [$var]]} val] + set ret [catch {$var} val] if { $ret != 0} { clientput [format "ERROR: failed to read %s" $var] return } else { - nxscript puttext $alias $val + set index [string first = $val] + if {$index >= 0} { + set txt [string trim [string range $val [expr $index + 1] end]] + nxscript puttext $alias $txt + } else { + clientput [format "ERROR: failed to read %s" $var] + } } } #======================================================================== @@ -57,7 +80,7 @@ proc writeTextAttribute {attName var} { clientput [format "ERROR: failed to read %s" $var] return } else { - nxscript putglobal $attName $val + nxscript putglobal $attName [string trim $val] } } #======================================================================= diff --git a/nxupdate.c b/nxupdate.c index e22304a9..fbaf427e 100644 --- a/nxupdate.c +++ b/nxupdate.c @@ -27,7 +27,7 @@ static int UpdateTask(void *pData){ update when intervall reached or when end */ if(time(NULL) >= self->nextUpdate || self->iEnd == 1){ - if(self->updateScript != NULL){ + if(self->updateScript != NULL && self->pCon != NULL){ InterpExecute(pServ->pSics,self->pCon,self->updateScript); } self->nextUpdate = time(NULL) + self->updateIntervall; diff --git a/ofac.c b/ofac.c index 0e111abd..cac85299 100644 --- a/ofac.c +++ b/ofac.c @@ -278,6 +278,7 @@ AddCommand(pInter,"TclReplaceDrivable",TclReplaceDrivable,NULL,NULL); AddCommand(pInter,"DrivableInvoke", TclDrivableInvoke,NULL,NULL); AddCommand(pInter,"UpdateFactory",UpdateFactory,NULL,NULL); + AddCommand(pInter,"allowexec",AllowExec,NULL,NULL); /* install site specific commands @@ -333,6 +334,7 @@ RemoveCommand(pSics,"MakeNXScript"); RemoveCommand(pSics,"MakeTclInt"); RemoveCommand(pSics,"UpdateFactory"); + RemoveCommand(pSics,"allowexec"); /* remove site specific installation commands diff --git a/rs232controller.c b/rs232controller.c index 924fc928..08b17a8b 100644 --- a/rs232controller.c +++ b/rs232controller.c @@ -124,6 +124,10 @@ int writeRS232(prs232 self, void *data, int dataLen) if(self->debug > 0) { printf("RS232 OUT: %s",(char *)data); + if(strchr((char *)data,'\n') == NULL) + { + puts("\n"); + } fflush(stdout); } @@ -172,6 +176,10 @@ int readRS232(prs232 self, void *data, int *dataLen) if(self->debug > 0) { printf("RS232 IN: %s",(char *)data); + if(strchr((char *)data,'\n') == NULL) + { + puts("\n"); + } fflush(stdout); } *dataLen = lRead; @@ -208,6 +216,10 @@ int readRS232TillTerm(prs232 self, void *data, int *datalen){ if(self->debug > 0) { printf("RS232 IN/TERM: %s",(char *)data); + if(strchr((char *)data,'\n') == NULL) + { + puts("\n"); + } fflush(stdout); } if(iRet == 0) @@ -265,7 +277,7 @@ int availableNetRS232(prs232 self) int transactRS232(prs232 self, void *send, int sendLen, void *reply, int replyLen) { - int iRet; + int iRet, len; assert(self); @@ -277,6 +289,15 @@ int transactRS232(prs232 self, void *send, int sendLen, return NOTCONNECTED; } + /* + if there is still data on the socket: clear it + while(availableRS232(self)){ + len = replyLen; + readRS232(self,reply,&len); + } + */ + + /* write data */ @@ -295,6 +316,10 @@ int transactRS232(prs232 self, void *send, int sendLen, if(self->debug > 0) { printf("RS232 IN/TRANS: %s",(char *)reply); + if(strchr((char *)reply,'\n') == NULL) + { + puts("\n"); + } fflush(stdout); } if(iRet == 0) @@ -559,6 +584,12 @@ int RS232Action(SConnection *pCon, SicsInterp *pSics, return 1; } } + else if(strcmp(argv[1],"debug") == 0) + { + self->debug = atoi(argv[2]); + SCSendOK(pCon); + return 1; + } else if(strcmp(argv[1],"timeout") == 0) { if(checkSet(pCon,argc,usMugger)) diff --git a/scan.c b/scan.c index cea764c6..24bbb806 100644 --- a/scan.c +++ b/scan.c @@ -34,6 +34,15 @@ extern void SNXFormatTime(char *pBuffer, int iLen); /* from nxdata.c */ +/*-----------------------------------------------------------------------*/ +static char *fixExtension(char *filename) +{ + if(strstr(filename,".hdf") != NULL) + { + changeExtension(filename,"dat"); + } + return filename; +} /*------------------------------------------------------------------------*/ char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon) { @@ -54,8 +63,7 @@ extern void SNXFormatTime(char *pBuffer, int iLen); { pRes = strdup("emergency.scn"); } - - return pRes; + return fixExtension(pRes); } /*--------------------- VarEntry Management --------------------------------*/ diff --git a/selvar.c b/selvar.c index 711274a1..609603ea 100644 --- a/selvar.c +++ b/selvar.c @@ -547,9 +547,16 @@ SCWrite(pCon,pBueffel,eError); return 0; } - + + /* + Removed, on demand of Lukas Keller, DMC sprintf(pBueffel,"%s %s %s",DRIVE,argv[0],argv[1]); - return InterpExecute(pSics,pCon,pBueffel); + return InterpExecute(pSics,pCon,pBueffel); + */ + snprintf(pBueffel,131,"ERROR: subcommand %s to %s not understood", + argv[1], argv[0]); + SCWrite(pCon,pBueffel,eError); + return 0; } else /* get case */ { diff --git a/sicscron.c b/sicscron.c index c0af5491..8198b2d4 100644 --- a/sicscron.c +++ b/sicscron.c @@ -137,3 +137,6 @@ SCSendOK(pCon); return 1; } + + + diff --git a/sicsstatus.tcl b/sicsstatus.tcl index 71315e2c..c06b255e 100644 --- a/sicsstatus.tcl +++ b/sicsstatus.tcl @@ -1,3 +1,10 @@ -# Counter counter -counter SetPreset 300.000000 -counter SetMode Timer +# Motor m4 +m4 sign 1.000000 +m4 SoftZero 0.000000 +m4 SoftLowerLim -22.004999 +m4 SoftUpperLim 21.995001 +m4 Fixed -1.000000 +m4 InterruptMode 0.000000 +m4 precision 0.010000 +m4 AccessCode 2.000000 +m4 poscount 10.000000 diff --git a/sicvar.c b/sicvar.c index 427b519e..3a4502a9 100644 --- a/sicvar.c +++ b/sicvar.c @@ -39,6 +39,7 @@ #include "fortify.h" #include #include +#include #include "sics.h" #include #include "splitter.h" @@ -411,11 +412,41 @@ } return 1; } - - +/*----------------------------------------------------------------------*/ +static int VarSetFromText(pSicsVariable self, SConnection *pCon, char *text) +{ + int status; + double dVal; + char pBueffel[132]; + + if(!SCMatchRights(pCon,self->iAccessCode)) + { + return 0; + } + if(self->eType == veText) + { + return VarSetText(self,text,SCGetRights(pCon)); + } + status = Tcl_GetDouble(InterpGetTcl(pServ->pSics), text,&dVal); + if(status != TCL_OK) + { + snprintf(pBueffel,131,"ERROR: failed to convert %s to number", + text); + SCWrite(pCon,pBueffel,eError); + return 0; + } + if(self->eType == veInt) + { + return VarSetInt(self,(int)dVal,SCGetRights(pCon)); + } + else if(self->eType == veFloat) + { + return VarSetFloat(self,(float)dVal,SCGetRights(pCon)); + } +} /*-------------------------------------------------------------------------- Variables understands some commands: - setrights : for setting uer rights + setrights : for setting user rights lock : for locking the variable interest : for notifictaion on value change uninterest : delete notification @@ -499,7 +530,9 @@ /* is control grabbed ? */ if(SCGetGrab(pCon) != 0) { - SCWrite(pCon,"ERROR: somebody else has grabbed control, Request REJECTED",eError); + SCWrite(pCon, + "ERROR: somebody else has grabbed control, Request REJECTED", + eError); DeleteTokenList(pList); return 0; } @@ -546,94 +579,74 @@ SCSendOK(pCon); return 1; } - /* now, only a new value is still possible */ - eStat = GetStatus(); - if( (eStat != eEager) && (eStat != eBatch) ) + else if(strcmp(pCurrent->text,"force") == 0) { - SCWrite(pCon, - "You cannot set variables while a scan is running",eError); - DeleteTokenList(pList); - return 0; - + /* + Undocumented feauture: force a set even while driving etc. + Internal privilege required to do this. + */ + if(!SCMatchRights(pCon,usInternal)) + { + return 0; + } + pCurrent = pCurrent->pNext; + if(!pCurrent) + { + SCWrite(pCon,"ERROR: new value missing for force",eError); + return 0; + } + Arg2Text(argc-2,&argv[2],pBueffel,255); + iRet = VarSetFromText(pVar,pCon,pBueffel); + if(iRet == 1) + { + SCSendOK(pCon); + } + SCparChange(pCon); + DeleteTokenList(pList); + return iRet; } - iRet = 0; - if(pCurrent) + else { - /* is it locked ? */ - if(pVar->iLock) - { - sprintf(pBueffel,"ERROR: variable %s is configured locked!", - argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - /* is control grabbed ? */ - if(SCGetGrab(pCon) != 0) - { - SCWrite(pCon,"ERROR: somebody else has grabbed control, Request REJECTED",eError); - DeleteTokenList(pList); - return 0; - } - /* do not care for typechecks if text */ - if(eTyp == veText) - { - Arg2Text(argc-1,&argv[1],pBueffel,255); - iRet = VarSetText(pVar,pBueffel,SCGetRights(pCon)); - } - else if(eTyp == veInt) - { - if(pCurrent->Type == eFloat) - { - iVal = (int)pCurrent->fVal; - } - else if(pCurrent->Type == eInt) - { - iVal = pCurrent->iVal; - } - else - { - sprintf(pBueffel,"Wrong Type: cannot assign %s to %s", - pCurrent->text, argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - iRet = VarSetInt(pVar,iVal,SCGetRights(pCon)); - } - else if(eTyp == veFloat) - { - if(pCurrent->Type == eFloat) - { - fVal = pCurrent->fVal; - } - else if(pCurrent->Type == eInt) - { - fVal = (float)pCurrent->iVal; - } - else - { - sprintf(pBueffel,"Wrong Type: cannot assign %s to %s", - pCurrent->text, argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - iRet = VarSetFloat(pVar,fVal,SCGetRights(pCon)); - } - if(!iRet) - { - sprintf(pBueffel,"Insufficient Privilege to change %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - SCSendOK(pCon); - SCparChange(pCon); - DeleteTokenList(pList); - return 1; - } + /* now, only a new value is still possible */ + eStat = GetStatus(); + if( (eStat != eEager) && (eStat != eBatch) ) + { + SCWrite(pCon, + "You cannot set variables while a scan is running",eError); + DeleteTokenList(pList); + return 0; + + } + iRet = 0; + if(pCurrent) + { + /* is it locked ? */ + if(pVar->iLock) + { + sprintf(pBueffel,"ERROR: variable %s is configured locked!", + argv[0]); + SCWrite(pCon,pBueffel,eError); + DeleteTokenList(pList); + return 0; + } + /* is control grabbed ? */ + if(SCGetGrab(pCon) != 0) + { + SCWrite(pCon,"ERROR: somebody else has grabbed control, Request REJECTED",eError); + DeleteTokenList(pList); + return 0; + } + Arg2Text(argc-1,&argv[1],pBueffel,255); + iRet = VarSetFromText(pVar,pCon,pBueffel); + if(iRet == 1) + { + SCSendOK(pCon); + } + SCparChange(pCon); + DeleteTokenList(pList); + return iRet; + } + } /* if we are here, no valid command was found */ SCWrite(pCon, diff --git a/status.c b/status.c index 27fc8063..6ccbf653 100644 --- a/status.c +++ b/status.c @@ -7,6 +7,9 @@ added callback facilities and interst command. Mark Koennecke, August 1997 + Updated in order to prevent status floods + Mark Koennecke, July 2004 + Copyright: Labor fuer Neutronenstreuung @@ -39,6 +42,7 @@ -----------------------------------------------------------------------------*/ #include #include +#include #include "fortify.h" #include #include "sics.h" @@ -48,7 +52,6 @@ #undef VALUECHANGE #define VALUECHANGE 2 - static Status eCode = eEager; static char *pText[] = { "Eager to execute commands", @@ -65,6 +68,7 @@ "Dead", "Waiting for User Input", "Counting/Driving", + "Working", NULL }; static char *iText[] = { @@ -82,10 +86,12 @@ "dead", "input", "count/drive", + "working", NULL }; static pICallBack pCall = NULL; static int fixed = 0; + static Status eCode = eEager; /*-------------------------------------------------------------------------*/ void KillStatus(void *pData) { diff --git a/status.h b/status.h index d54c893b..1d9dca09 100644 --- a/status.h +++ b/status.h @@ -22,7 +22,8 @@ eHalted, eDead, eInput, - eCountDrive + eCountDrive, + eWorking } Status; /* for status display */ @@ -43,6 +44,7 @@ Status GetStatus(void); void GetStatusText(char *buf, int iBufLen); + int UserStatus(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ResetStatus(SConnection *pCon, SicsInterp *pSics, void *pData, diff --git a/synchronize.c b/synchronize.c index ee955389..51d6e205 100644 --- a/synchronize.c +++ b/synchronize.c @@ -229,7 +229,7 @@ int Synchronize(SConnection *pCon, SicsInterp *pSics, void *pData, { if(test > 0) { - strcat(pBueffel,pRead); + strncat(pBueffel,pRead, 2047 - strlen(pBueffel)); } } if(strstr(pBueffel,"TRANSACTIONFINISHED") != NULL) @@ -283,6 +283,8 @@ int Synchronize(SConnection *pCon, SicsInterp *pSics, void *pData, tell everybody that we have sync'ed */ ServerWriteGlobal("Simulation Server has SYNCHRONIZED!",eWarning); + ServerWriteGlobal("Fixed motors may not have correct positions", + eWarning); return 1; } diff --git a/telnet.c b/telnet.c index b0f5db36..6153f47d 100644 --- a/telnet.c +++ b/telnet.c @@ -105,7 +105,7 @@ if(self->pCon->iEnd) { - if(self->pCon->inUse > 0) + if(SCActive(self->pCon)) { return 1; } @@ -201,7 +201,7 @@ /* check for end */ if(self->pCon->iEnd) { - if(self->pCon->inUse > 0) + if(SCActive(self->pCon)) { return 1; } diff --git a/test.tcl b/test.tcl index b5ef908c..ca221667 100644 --- a/test.tcl +++ b/test.tcl @@ -10,7 +10,7 @@ rename scan stscan #-------- a home for this, everything else is in relation to this -set shome /data/koenneck/src +set shome /afs/psi.ch/user/k/koennecke/Tru64/src @@ -48,7 +48,7 @@ ServerOption TecsPort 9753 ServerOption statusfile sicsstatus.tcl -ServerOption ServerPort 3006 +ServerOption ServerPort 2911 # the port number the server is going to listen at. The client MUST know # this number in order to connect. It is in client.ini @@ -172,9 +172,9 @@ set dornen(Timeout) 5000 set d2003(Host) psts233 set d2003(Port) 3004 set d2003(Timeout) 20000 -VelocitySelector nvs tilt dornier2003 d2003 +#VelocitySelector nvs tilt dornier2003 d2003 -#VelocitySelector nvs tilt SIM +VelocitySelector nvs tilt SIM nvs add -20 28800 nvs add 3800 4500 nvs add 5900 6700 @@ -487,7 +487,7 @@ Publish batchrun User #------- test of RS232Controller -#MakeRS232Controller hugo psts213 3004 +#MakeRS232Controller hugo psts233 3004 #-------------------------- batch run issue VarMake BatchRoot Text User diff --git a/userscan.c b/userscan.c index 80f23032..7b2a8c54 100644 --- a/userscan.c +++ b/userscan.c @@ -49,7 +49,7 @@ static int UserCount(pScanData self, int iPoint) /* invoke command */ snprintf(pBueffel,511,"%s %d",self->pCommand, iPoint); - status = Tcl_GlobalEval(self->pSics->pTcl,pBueffel); + status = Tcl_Eval(self->pSics->pTcl,pBueffel); if(status != TCL_OK) { sprintf(pBueffel,"ERROR in count script: %s", diff --git a/varlog.c b/varlog.c index e72b0fa6..965eada0 100644 --- a/varlog.c +++ b/varlog.c @@ -418,7 +418,8 @@ static void VarLogDumpFile(pVarLog self, FILE *fd) iRet = VarlogGetMean(self,&fMean,&fStdDev); if(!iRet) { - SCWrite(pCon,"ERROR: Invalid logging list",eError); + SCWrite(pCon,"WARNING: No mean and stddev log values available ", + eWarning); return 0; } sprintf(pBueffel,"%s.Mean = %8.2f %s.StdDev = %8.2f",