Index: drsdaq/DAQReadout.cc
===================================================================
--- drsdaq/DAQReadout.cc	(revision 51)
+++ drsdaq/DAQReadout.cc	(revision 55)
@@ -11,4 +11,6 @@
 #include "DAQReadout.h"
 #include "SlowData.h"
+
+#define TMPNAME "/tmp/__tmp__drsdaq__"
 
 static const char* daq_state_str[] = {"active", "stopped"};
@@ -64,15 +66,16 @@
 
   // Initialize status structure
-  daq_state	    = stopped;
-  daq_runtype	    = data;
-  Socket	    = -1;
-  Exit		    = false;
-  CalibrationRead   = false;
-  NumEvents		= 0;
-  NumEventsRequested	= 100;
-  NumBoards		= 0;
-  FirstBoard		= 0;
-  LastBoard		= -1;
-  
+  daq_state	     = stopped;
+  daq_runtype	     = data;
+  Socket	     = -1;
+  Exit		     = false;
+  CalibrationRead    = false;
+  NumEvents	     = 0;
+  NumEventsRequested = 100;
+  NumBoards	     = 0;
+  FirstBoard	     = 0;
+  LastBoard	     = -1;
+  CmdFromSocket      = false;
+      
   // Read configuration file
   FILE *File;
@@ -83,4 +86,5 @@
     printf("Reading drsdaq configuration file %s\n", Configfile);
     ReadCard("LogFile",             fLogFile,           's', File);
+    ReadCard("MaxLogLines",        &fMaxLogLines,       'U', File);
     ReadCard("RawDataPath",         fRawDataPath,       's', File);
     ReadCard("RotateWave",         &fRotateWave,        'I', File);
@@ -100,9 +104,15 @@
     fLastSample = kNumberOfBins;
   }
-
-  // Open log file and print configuration
-  if ((Logfile = fopen(fLogFile, "a")) == NULL)
-    fprintf(stderr,"Warning: Could not open log file '%s'\n", fLogFile);
-  else PrintMessage(MsgToLog,"********** Logging started **********\n");
+  
+  // Truncate log file to given number of lines
+  char ShellCmd[MAX_COM_SIZE]; 
+  snprintf(ShellCmd, sizeof(ShellCmd), "tail --lines=%u %s >%s; cp %s %s; rm %s", fMaxLogLines, fLogFile, TMPNAME, TMPNAME, fLogFile, TMPNAME);
+  if (system(ShellCmd) != 0) printf("Warning: Could not truncate log file '%s' to %u lines\n", fLogFile, fMaxLogLines);
+
+  // Open log file
+  if ((Logfile = fopen(fLogFile, "a")) == NULL) printf("Warning: Could not open log file '%s'\n", fLogFile);
+  PrintMessage(MsgToLog,"********** Logging started **********\n");
+  
+  // Print configuration
   cmd_config();
 
@@ -165,18 +175,16 @@
 // --------------------------------
 
-int DAQReadout::CommandControl(char *Command, bool FromSocket) {
-
-  if (strlen(Command) < 2 ) return 0;  // Ignore commands with only '/n'
-  if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0';  // Remove '/n'
-  
+void DAQReadout::CommandControl(char *Command) {
+
+  if (strlen(Command)==0) return;  // Ignore empty commands
+
   if(Command[0]=='.') {   // Shell command
     system(&(Command[1]));
-    return 0;
+    return;
   }
 
   for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = "";  // All pointers point initially to empty string
   NParam = ParseInput(Command, Param);
-	
-  CmdFromSocket = FromSocket;
+
   for(CmdNumber=0; CmdNumber<sizeof(CommandList)/sizeof(CL_Struct); CmdNumber++)
     if (Match(Param[0], CommandList[CmdNumber].Name)) {
@@ -184,8 +192,8 @@
       else if(CommandList[CmdNumber].NeedNotBusy && NumBoards==0) PrintMessage("No mezzanine boards available\n");
       else (this->*CommandList[CmdNumber].CommandPointer)();
-      return 0;  
-    }
-  PrintMessage("Unknown command: %s\n",Param[0]);
-  return 0;
+      return;  
+    }
+  PrintMessage("Unknown command '%s'\n",Param[0]);
+  return;
 }
   	  
@@ -194,10 +202,10 @@
   time_t ActualT;
   time (&ActualT);
-  PrintMessage(CmdFromSocket ? MsgToSocket:MsgToConsole, "%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60);
+  PrintMessage("%d:%02d:%02d\n", (int) difftime(ActualT, StartTime)/3600, ((int) difftime(ActualT, StartTime)/60)%60, (int) difftime(ActualT, StartTime)%60);
 } 
 
 // Print disk space
 void DAQReadout::cmd_disk() {
-  PrintMessage(CmdFromSocket ? MsgToSocket:MsgToConsole, "Free disk space (%s) [MB]: %lu\n", fRawDataPath, CheckDisk(fRawDataPath));
+  PrintMessage("Free disk space (%s) [MB]: %lu\n", fRawDataPath, CheckDisk(fRawDataPath));
 } 
 
@@ -210,10 +218,9 @@
 // Print DAQ configuration
 void DAQReadout::cmd_config() {
-  PrintMessage("LogFile: %s\tRawDataPath: %s\n"
+  PrintMessage("LogFile: %s\tMaxLogLines: %u\tRawDataPath: %s\n"
       	       "RotateWave: %d\t\tFirstSample: %d\t\tLastSample: %d\n"
      	       "MinDiskSpaceMB: %u\tMaxFileSizeMB: %d\tCCPort: %d\n"
-      	       "FirstVMESlot: %d\t\tLastVMESlot: %d\n"
-	       "HVFeedbackConfig: \t%s\n",
-    fLogFile,fRawDataPath,fRotateWave,fFirstSample,fLastSample,fMinDiskSpaceMB,
+      	       "FirstVMESlot: %d\t\tLastVMESlot: %d\t\tHVFeedbackConfig: %s\n",
+    fLogFile,fMaxLogLines,fRawDataPath,fRotateWave,fFirstSample,fLastSample,fMinDiskSpaceMB,
     fMaxFileSizeMB,fCCPort,fFirstVMESlot,fLastVMESlot,fHVFeedbackConfig);
 }
@@ -278,5 +285,5 @@
   // Create DAQ thread
   if ((pthread_create(&thread_DAQ, NULL, (void * (*)(void *)) DAQ,(void *) this)) != 0)
-    perror("pthread_create failed with DAQ thread");
+    PrintMessage("pthread_create failed with DAQ thread (%s)\n",strerror(errno));
   else {
     daq_state = active;
@@ -552,5 +559,5 @@
     LastBoard = drs->GetNumberOfBoards()-1;
   } 
-  else if (NParam==2 && atoi(Param[1]) >= 0 && atoi(Param[1]) < NumBoards) {
+  else if (NParam==2 && atoi(Param[1])>=0 && atoi(Param[1])<NumBoards) {
     FirstBoard = atoi(Param[1]);
     LastBoard = FirstBoard;
@@ -565,5 +572,5 @@
 } 
 
-// Print help
+// Print help (only to console or socket, not to log file)
 void DAQReadout::cmd_help() {
   char Buffer[MAX_COM_SIZE];
@@ -978,5 +985,5 @@
   
   EHeader->EventNumber = NumEvents;
-  EHeader->TriggerType = 0x0;
+  EHeader->TriggerType = (daq_runtype == data) ? 1 : 0;
   EHeader->Second = Time.tv_sec;
   EHeader->Microsecond = Time.tv_usec;
@@ -1003,9 +1010,10 @@
 }
 
-// Print message to screen, log file and socket
+// Print message to log file, and screen or socket (depending on command origin)
 void DAQReadout::PrintMessage(const char *Format, ...) {
   va_list ArgumentPointer;
-  va_start(ArgumentPointer, Format); 
-  PrintMessage(MsgToConsole|MsgToLog|MsgToSocket, Format, ArgumentPointer);
+  va_start(ArgumentPointer, Format);
+  if(CmdFromSocket) PrintMessage(MsgToSocket|MsgToLog, Format, ArgumentPointer);
+  else PrintMessage(MsgToConsole|MsgToLog, Format, ArgumentPointer);
   va_end(ArgumentPointer);
 }
@@ -1069,53 +1077,53 @@
       while(!isspace(*Command) && *Command!='\0') Command++;
     }
-    *Command++ = '\0';
+    if(*Command != '\0') *Command++ = '\0';
     Count++;
-  };
+  }
   return Count;
 }
 
-// ReadCard function by F. Goebel
-int ReadCard(const char *card_flag, void *store, char type, FILE *fptr) {
-  
-  char *card_name, *card_val, line[160];
-
-  rewind(fptr);
-
-  while (fgets(line, 160, fptr) != NULL) {    // Read line by line
-    card_name = strtok(line," \t\n");
-    card_val  = strtok(NULL," \t\n");
+// ReadCard function (original version by F. Goebel)
+// Data is read into an array if MaxNum is larger than 1
+bool ReadCard(const char *card_flag, void *store, char Type, FILE *File, unsigned int MaxNum) {
+  
+  char *card_name, *card_val, Buffer[MAX_COM_SIZE];
+  unsigned int Count=0;
+  
+  rewind(File);
+
+  while (fgets(Buffer, sizeof(Buffer), File) != NULL) {    // Read line by line
+    card_name = strtok(Buffer," \t\n");
     
-    if (   card_name    != NULL  && card_val     != NULL   // Comment or empty line?
-        && card_name[0] != '*'   && card_name[0] != '#') {
-      
-      if (strcmp(card_name, card_flag)!=0) {   // Is this the card name we are looking for?
-	continue;  
+     // Ignore empty lines, comments, and skip if card name does not match
+    if (card_name==NULL || card_name[0]=='#' || strcmp(card_name, card_flag)!=0) continue;
+
+    // Read numbers of given type (if MaxNum>1 read array)
+    while ((card_val=strtok(NULL," \t\n")) != NULL && Count++<MaxNum) {
+      switch (Type) {
+	case 'I': *(((int *&) store)++) = (int) strtol(card_val, NULL, 10);
+	      	  break;
+	case 'i': *(((short *&) store)++) = (short) strtol(card_val, NULL, 10);
+	      	  break;
+	case 'U': *(((unsigned int *&) store)++) = (unsigned int) strtoul(card_val, NULL, 10);
+	      	  break;
+	case 'u': *(((unsigned short *&) store)++) = (unsigned short) strtoul(card_val, NULL, 10);
+	      	  break;
+	case 'f': *(((float *&) store)++) = atof(card_val);
+	      	  break;
+	case 'd': *(((double *&) store)++) = atof(card_val);
+	      	  break;
+	case 's': sprintf((char *) store, "%s", card_val);
+	      	  break;
+	case 'c': *((char *) store) = card_val[0];
+	      	  break;
+	default:  fprintf(stderr,"Warning: Unknown type '%c' for reading of configuration file\n", Type);
+	      	  return false;
       }
-
-      switch (type) {
-      case 'I':	*((int *) store)   = (int) strtol(card_val, (char**)NULL, 10);
-	      	break;
-      case 'i':	*((short *) store) = (short) strtol(card_val, (char**)NULL, 10);
-	      	break;
-      case 'U':	*((unsigned int *) store) = (unsigned int) strtoul(card_val, (char**)NULL, 10);
-	      	break;
-      case 'u':	*((unsigned short *) store) = (unsigned short) strtoul(card_val, (char**)NULL, 10);
-	      	break;
-      case 'f': *((float *) store) = atof(card_val);
-	      	break;
-      case 'd':	*((double *) store) = atof(card_val);
-	      	break;
-      case 's':	sprintf((char *) store,"%s",card_val);
-	      	break;
-      case 'c':	*((char *) store) = card_val[0];
-	      	break;
-      default:	fprintf(stderr,"WARNING: ReadCard: unknown type: %c\n", type);
-	      	return -2;
-      }
-      return 0; // Found card name
-    }
-  }
-  fprintf(stderr,"WARNING: ReadCard: card: %s not found\n", card_flag);
-  return -1;
+    }
+    return true;  // Finished reading data for card name
+    
+  }
+  fprintf(stderr,"Warning: Configuration value %s not found\n", card_flag);
+  return false;
 }
 
Index: drsdaq/DAQReadout.h
===================================================================
--- drsdaq/DAQReadout.h	(revision 51)
+++ drsdaq/DAQReadout.h	(revision 55)
@@ -36,5 +36,4 @@
     unsigned int CmdNumber;
     FILE *Logfile;    
-    bool CmdFromSocket;       	// Current command issued via socket
     void PrintUsage();
     bool CalibrationRead;
@@ -52,4 +51,5 @@
     // Configuration data
     char fLogFile[MAX_PATH];
+    unsigned int fMaxLogLines;
     char fRawDataPath[MAX_PATH];
     int fMinDiskSpaceMB;   // Minimum required disk space in MBytes
@@ -64,6 +64,7 @@
     
     // Status variables    
-    int NParam;       	      	// Number of parameters
+    int NParam;       	      	// Number of command parameters
     const char *Param[MAX_NUM_TOKEN]; // Pointers to parameters
+    bool CmdFromSocket;       	// Current command issued via socket
     int NumBoards;
     int FirstBoard;
@@ -104,5 +105,5 @@
     void cmd_fresponse(); void cmd_fconfig();
 
-    int CommandControl(char*, bool);  
+    void CommandControl(char*);  
     void StartDRS();
     void StopDRS();
@@ -133,5 +134,5 @@
 int ParseInput(char*, const char *Param[]);
 int CheckDisk(char*);
-int ReadCard(const char *, void *, char, FILE *);
+bool ReadCard(const char *, void *, char, FILE *, unsigned int=1);
 
 #endif
Index: drsdaq/HVFeedback.cc
===================================================================
--- drsdaq/HVFeedback.cc	(revision 51)
+++ drsdaq/HVFeedback.cc	(revision 55)
@@ -31,4 +31,11 @@
   snprintf(Filename,sizeof(Filename),"%s/SlowData/", m->fRawDataPath);
   SlowDataClass = new SlowData(m, "HVFB", Filename);
+
+  // Initialise with zero content
+  Average    = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
+  Sigma      = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
+  Response   = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
+  Target     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
+  Buffer     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();  
 
   // Read configuration file
@@ -51,15 +58,10 @@
     ReadCard("HVControlPort",       &fHVControlPort,     'I', File);
     ReadCard("MaxCmdAckDelay",      &fMaxCmdAckDelay,    'I', File);
+    ReadCard("DefaultResponse",      Response,      	 'f', File, m->NumBoards*kNumberOfChips*kNumberOfChannels);
     fclose(File);
   }
   PrintConfig();
-
-  // Initialise with zero content
-  Average    = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Sigma      = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Response   = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Target     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
-  Buffer     = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();  
-
+ 
+  // Initial state
   Gain = 1;
   SetFBMode(FB_Off);
Index: drsdaq/History.txt
===================================================================
--- drsdaq/History.txt	(revision 51)
+++ drsdaq/History.txt	(revision 55)
@@ -9,7 +9,7 @@
 26/3/2009   Added PixelMap translation to communication with HV control.
 30/3/2009   Added feedback gain. Checked into repository.
-1/4/2009    Changes many 'char *' to 'const char *' to honour compiler warning
+1/4/2009    Changed many 'char *' to 'const char *' to honour compiler warning
             on ihp-pc26 (newer version of g++ than on eth-vme02)
-2/4/2009    Intoduced check for magic number in RawDataCTX.cc
+2/4/2009    Introduced check for magic number in RawDataCTX.cc
 3/4/2009    Added frequency and scale factor transmission to socket protocol
 6/4/2009    Allowed reading of data via read command also while DAQ is active.
@@ -30,2 +30,6 @@
 28/5/2009   Replaced NCMCBoards by NBoards for clarity. Added line editing
     	    capability with the readline library.
+29/5/2009   Number of lines in log file limited to configurable number.
+4/6/2009    Config file can contain array of numbers. Reading of config file now
+    	    safe for buffer overflow. RawDataCTX class take the possibility of
+	    varying event data size into account.
Index: drsdaq/RawDataCTX.cc
===================================================================
--- drsdaq/RawDataCTX.cc	(revision 51)
+++ drsdaq/RawDataCTX.cc	(revision 55)
@@ -105,6 +105,6 @@
       fprintf(fptr, "*** Board %d ***\n", i);
       fprintf(fptr, "Serial number:            %d\n", BStruct[i].SerialNo);
-      fprintf(fptr, "Sampling frequency [GHz]: %.3f\n", BStruct[i].NomFreq);
-      fprintf(fptr, "Temperature [C]:          %.3f\n", BStruct[i].BoardTemp);  
+      fprintf(fptr, "Sampling frequency:       %.3f GHz\n", BStruct[i].NomFreq);
+      fprintf(fptr, "Temperature:              %.3f deg C\n", BStruct[i].BoardTemp);  
       fprintf(fptr, "Scale factor:             %.3f\n", BStruct[i].ScaleFactor);
     }     
@@ -138,36 +138,26 @@
   }
   
-/*   // Move file pointer to desired event header (if zero read next event)
-  if(EventNo!=0 && fseek(Rawfile, RHeader->RunHeaderSize+RHeader->BoardStructureSize*RHeader->NBoards+(EventNo-1)*(RHeader->EventHeaderSize+RHeader->NBoards*RHeader->NChips*
-      RHeader->NChannels*RHeader->Samples*sizeof(short)), SEEK_SET)!=0) {
+  // Move file pointer to desired event header (if zero read next event)
+  bool SEEK_OK=true;
+  if (EventNo!=0 && fseek(Rawfile, RHeader->RunHeaderSize+RHeader->BoardStructureSize*RHeader->NBoards, SEEK_SET) != 0) SEEK_OK=false;
+  while(SEEK_OK) {
+    if (fread(EHeader, RHeader->EventHeaderSize, 1, Rawfile) != 1) {
+      if (feof(Rawfile)==0) {
+	if (!Silent) printf("Error: Could not read event header\n");
+	return CTX_EHEADER;
+      }
+      else return CTX_EOF;  
+    }
+    else {
+      if (EHeader->EventNumber==EventNo || EventNo==0) break;
+      if (fseek(Rawfile, EHeader->EventSize, SEEK_CUR) != 0) SEEK_OK = false;
+    }
+  }
+  if(!SEEK_OK) {
     if(!Silent) printf("Error: Could not move to requested event\n");
     return CTX_SEEK;
   }
- */
 
-  // Move file pointer to desired event header (if zero read next event)
-  if (EventNo != 0) {
-    bool SEEK_OK=true;
-    if (fseek(Rawfile, RHeader->RunHeaderSize+RHeader->BoardStructureSize*RHeader->NBoards, SEEK_SET) != 0) SEEK_OK=false;
-    while(SEEK_OK) {
-      if (fread(EHeader, RHeader->EventHeaderSize, 1, Rawfile) != 0) SEEK_OK = false;
-      else {
-        if (EHeader->EventNumber==EventNo) break;
-        if (fseek(Rawfile, EHeader->EventSize, SEEK_CUR) != 0) SEEK_OK = false;
-      }
-    }
-    if(!SEEK_OK) {
-      if(!Silent) printf("Error: Could not move to requested event\n");
-      return CTX_SEEK;
-    }
-  }
-  // Read event header
-  else if (fread(EHeader, RHeader->EventHeaderSize, 1, Rawfile) != 1) {
-    if (feof(Rawfile)==0) {
-      if (!Silent) printf("Error: Could not read event header\n");
-      return CTX_EHEADER;
-    }
-    else return CTX_EOF;  
-  }
+  // Read event data
   if(fread(Data, 1, EHeader->EventSize, Rawfile) != EHeader->EventSize) {
     if(!Silent) printf("Error: Could not read (all) event data\n");
@@ -191,3 +181,2 @@
   return FileOpen;
 }
-
Index: drsdaq/drsdaq.cpp
===================================================================
--- drsdaq/drsdaq.cpp	(revision 51)
+++ drsdaq/drsdaq.cpp	(revision 55)
@@ -142,8 +142,9 @@
 
     strftime(Buf,MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL))));
-    m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s", Buf, Command);
-
+    m->PrintMessage(MsgToLog, "CONSOLE(%s)> %s\n", Buf, Command);
+
+    // Process command
     pthread_mutex_lock(&m->control_mutex);
-    m->CommandControl(Command, false);
+    m->CommandControl(Command);
     pthread_mutex_unlock(&m->control_mutex);
 
@@ -224,11 +225,14 @@
 	break;
       }
+      if (Command[strlen(Command)-1]=='\n') Command[strlen(Command)-1]='\0';  // Remove trailing newline
       
-      strftime(Buf,MAX_COM_SIZE,"%d/%m/%y %X", localtime(&(Time=time(NULL))));
-      m->PrintMessage(MsgToLog,"SOCKET(%s)> %s%s",Buf, Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
-      m->PrintMessage(MsgToConsole,"SOCKET> %s%s",Command, Command[strlen(Command)-1]=='\n' ? "":"\n");
-     
-      pthread_mutex_lock(&m->control_mutex);       
-      m->CommandControl(Command, true);	// Process CC command
+      strftime(Buf, MAX_COM_SIZE, "%d/%m/%y %X", localtime(&(Time=time(NULL))));
+      m->PrintMessage(MsgToConsole|MsgToLog, "SOCKET(%s)> %s\n", Buf, Command);
+
+      // Process command     
+      pthread_mutex_lock(&m->control_mutex);
+      m->CmdFromSocket = true;       
+      m->CommandControl(Command);
+      m->CmdFromSocket = false;  
       pthread_mutex_unlock(&m->control_mutex);
     }
