Index: trunk/ppSim/src/ppSimSequence.c
===================================================================
--- trunk/ppSim/src/ppSimSequence.c	(revision 27657)
+++ trunk/ppSim/src/ppSimSequence.c	(revision 27967)
@@ -1,6 +1,4 @@
 # include "ppSimSequence.h"
 # include <sys/stat.h>
-
-// XXX Memory leaks in string variables
 
 int main (int argc, char **argv) {
@@ -135,20 +133,62 @@
     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
 
-    psMetadataItem *item = psMetadataLookup (config, "SEQUENCE");
-    if (item == NULL) {
-        psLogMsg ("ppSimSequence", PS_LOG_WARN, "missing SEQUENCE description");
-        exit (PS_EXIT_CONFIG_ERROR);
-    }
-
+    // global camera option (if not set, we look in each sequence)
+    if (camera == NULL) {
+	camera = psMetadataLookupStr (&status, config, "CAMERA");
+    }
+
+    psArray *files = NULL;
     psArray *sequences = NULL;
-    if (item->type == PS_DATA_METADATA) {
-        sequences = psArrayAlloc(1);
-        sequences->data[0] = psMemIncrRefCounter (item->data.V);
-    } else {
-        if (item->type != PS_DATA_METADATA_MULTI)  {
-            psLogMsg ("ppSimSequence", PS_LOG_WARN, "SEQUENCE is not MULTI or METADATA");
-            exit (1);
-        }
-        sequences = psListToArray (item->data.list);
+
+    { // find the FILERULE (if it exists) to set the file extension (.fits is default)
+	psMetadataItem *filerule = psMetadataLookup (config, "FILERULE");
+	if (filerule == NULL) {
+	    psLogMsg ("ppSimSequence", PS_LOG_INFO, "no FILERULE, assuming .fits ending");
+	    files = psArrayAlloc(1);
+	    files->data[0] = psStringCopy("fits");
+	    goto sequence;
+	} 
+	if (filerule->type == PS_DATA_METADATA_MULTI) {
+	    psArray *rules = psListToArray (filerule->data.list);
+	    psAssert (rules, "failed to get array from list?");
+	    psAssert (rules->n > 1, "supposed to be multiple entries in the list?");
+	    files = psArrayAllocEmpty(rules->n);
+	    for (int i = 0; i < rules->n; i++) {
+		psMetadataItem *item = rules->data[i];
+		if (item->type != PS_DATA_STRING) {
+		    psLogMsg ("ppSimSequence", PS_LOG_WARN, "invalid FILERULE type");
+		    exit (PS_EXIT_CONFIG_ERROR);
+		}
+		psArrayAdd (files, 16, item->data.str);
+	    }
+	    goto sequence;
+	}
+	if (filerule->type == PS_DATA_STRING) {
+	    files = psArrayAlloc(1);
+	    files->data[0] = psStringCopy(filerule->data.str);
+	    goto sequence;
+	}
+	psLogMsg ("ppSimSequence", PS_LOG_WARN, "invalid FILERULE type");
+	exit (PS_EXIT_CONFIG_ERROR);
+    }
+
+sequence:
+    { // find the set of sequences which define the ppSim data to be produced
+	psMetadataItem *item = psMetadataLookup (config, "SEQUENCE");
+	if (item == NULL) {
+	    psLogMsg ("ppSimSequence", PS_LOG_WARN, "missing SEQUENCE description");
+	    exit (PS_EXIT_CONFIG_ERROR);
+	}
+
+	if (item->type == PS_DATA_METADATA) {
+	    sequences = psArrayAlloc(1);
+	    sequences->data[0] = psMemIncrRefCounter (item->data.V);
+	} else {
+	    if (item->type != PS_DATA_METADATA_MULTI)  {
+		psLogMsg ("ppSimSequence", PS_LOG_WARN, "SEQUENCE is not MULTI or METADATA");
+		exit (1);
+	    }
+	    sequences = psListToArray (item->data.list);
+	}
     }
 
@@ -172,4 +212,8 @@
             camera = psMetadataLookupStr (&status, sequence, "CAMERA");
         }
+	if (!camera) {
+            psLogMsg ("ppSimSequence", PS_LOG_WARN, "CAMERA is not defined");
+            exit (1);
+	}
 
         psString injectCommandReal = NULL;
@@ -180,17 +224,25 @@
 
         if (!strcasecmp (type, "BIAS")) {
-            ppSimSequenceBias (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal);
+            ppSimSequenceBias (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal, files);
+	    psFree (injectCommandReal);
+	    psFree (ppSimCommandReal);
             continue;
         }
         if (!strcasecmp (type, "DARK")) {
-            ppSimSequenceDark (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal);
+            ppSimSequenceDark (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal, files);
+	    psFree (injectCommandReal);
+	    psFree (ppSimCommandReal);
             continue;
         }
         if (!strcasecmp (type, "FLAT")) {
-            ppSimSequenceFlat (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal);
+            ppSimSequenceFlat (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal, files);
+	    psFree (injectCommandReal);
+	    psFree (ppSimCommandReal);
             continue;
         }
         if (!strcasecmp (type, "OBJECT")) {
-            ppSimSequenceObject (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal);
+            ppSimSequenceObject (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal, files);
+	    psFree (injectCommandReal);
+	    psFree (ppSimCommandReal);
             continue;
         }
Index: trunk/ppSim/src/ppSimSequence.h
===================================================================
--- trunk/ppSim/src/ppSimSequence.h	(revision 27657)
+++ trunk/ppSim/src/ppSimSequence.h	(revision 27967)
@@ -12,8 +12,8 @@
 #include <psastro.h>
 
-bool ppSimSequenceBias 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand);
-bool ppSimSequenceDark 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand);
-bool ppSimSequenceFlat 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand);
-bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand);
+bool ppSimSequenceBias 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
+bool ppSimSequenceDark 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
+bool ppSimSequenceFlat 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
+bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
 
 #endif
Index: trunk/ppSim/src/ppSimSequenceBias.c
===================================================================
--- trunk/ppSim/src/ppSimSequenceBias.c	(revision 27657)
+++ trunk/ppSim/src/ppSimSequenceBias.c	(revision 27967)
@@ -1,5 +1,5 @@
 # include "ppSimSequence.h"
 
-bool ppSimSequenceBias (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand) {
+bool ppSimSequenceBias (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files) {
 
     bool status, setLevel, setRange;
@@ -14,5 +14,5 @@
     int nImage = 0;
     for (int i = 0; i < nImages; i++) {
-	    
+	        
 	// define the output filename
 	psString filename = NULL;
@@ -30,19 +30,23 @@
 	if (setLevel) psStringAppend (&command, " -biaslevel %f", level);
 	if (setRange) psStringAppend (&command, " -biasrange %f", range);
-      
+          
 	psStringAppend (&command, " %s", filename);
 
 	fprintf (simfile, "%s\n", command);
 	psFree (command);
-			    
+			        
 	// define the inject command
 	// path should be dirname/filename
-	command = psStringCopy (injectCommand);
-	psStringAppend (&command, " %s*.fits",    filename);
-	fprintf (inject, "%s\n", command);
-	psFree (command);
+	
+	// we use the filename above (really the file root) to construct the filenames
+	for (int i = 0; i < files->n; i++) {
+	    command = psStringCopy (injectCommand);
+            psStringAppend (&command, " %s.%s", filename, (char *) files->data[i]);
+            fprintf (inject, "%s\n", command);
+	    psFree (command);
+	}
+
 	psFree (filename);
-
-	nImage ++;
+        nImage ++;
     }
     return true;
Index: trunk/ppSim/src/ppSimSequenceDark.c
===================================================================
--- trunk/ppSim/src/ppSimSequenceDark.c	(revision 27657)
+++ trunk/ppSim/src/ppSimSequenceDark.c	(revision 27967)
@@ -1,5 +1,5 @@
 # include "ppSimSequence.h"
 
-bool ppSimSequenceDark (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand) {
+bool ppSimSequenceDark (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files) {
 
     bool status, setRate;
@@ -39,5 +39,5 @@
 
 	    psStringAppend (&command, "%s -type DARK", ppSimCommand);
-      
+          
 	    if (setRate) {
 		double frnd = psRandomUniform(rng);
@@ -52,15 +52,19 @@
 	    fprintf (simfile, "%s\n", command);
 	    psFree (command);
-			    
+			        
 	    // define the inject command
 	    // path should be dirname/filename
-	    command = psStringCopy (injectCommand);
-	    psStringAppend (&command, " %s*.fits",    filename);
-	    fprintf (inject, "%s\n", command);
-	    psFree (command);
-	    psFree (filename);
+	
+	    // we use the filename above (really the file root) to construct the filenames
+	    for (int i = 0; i < files->n; i++) {
+		command = psStringCopy (injectCommand);
+		psStringAppend (&command, " %s.%s", filename, (char *) files->data[i]);
+		fprintf (inject, "%s\n", command);
+		psFree (command);
+	    }
 
-	    nImage ++;
-	}
+            psFree (filename);
+            nImage ++;
+        }
     }
     return true;
Index: trunk/ppSim/src/ppSimSequenceFlat.c
===================================================================
--- trunk/ppSim/src/ppSimSequenceFlat.c	(revision 27657)
+++ trunk/ppSim/src/ppSimSequenceFlat.c	(revision 27967)
@@ -1,5 +1,5 @@
 # include "ppSimSequence.h"
 
-bool ppSimSequenceFlat (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand) {
+bool ppSimSequenceFlat (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files) {
 
     bool status;
@@ -26,5 +26,5 @@
 	// loop over the filters & exposure times
 	for (int j = 0; j < nSetup; j++) {
-	    
+	        
 	    // define the output filename
 	    psString filename = NULL;
@@ -50,11 +50,15 @@
 	    // define the inject command
 	    // path should be dirname/filename
-	    command = psStringCopy (injectCommand);
-	    psStringAppend (&command, " %s*.fits",    filename);
-	    fprintf (inject, "%s\n", command);
-	    psFree (command);
-	    psFree (filename);
+	
+	    // we use the filename above (really the file root) to construct the filenames
+	    for (int i = 0; i < files->n; i++) {
+		command = psStringCopy (injectCommand);
+		psStringAppend (&command, " %s.%s", filename, (char *) files->data[i]);
+		fprintf (inject, "%s\n", command);
+		psFree (command);
+	    }
 
-	    nImage ++;
+            psFree (filename);
+            nImage ++;
 	}
     }
Index: trunk/ppSim/src/ppSimSequenceObject.c
===================================================================
--- trunk/ppSim/src/ppSimSequenceObject.c	(revision 27657)
+++ trunk/ppSim/src/ppSimSequenceObject.c	(revision 27967)
@@ -1,5 +1,5 @@
 # include "ppSimSequence.h"
 
-bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand) {
+bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files) {
 
     bool status;
@@ -34,12 +34,12 @@
     // loop over the filters & exposure times
     for (int i = 0; i < filters->n; i++) {
-	    
+	        
 	// offset parameters
 	float dR = psMetadataLookupF32 (&status, sequence, "OFFSET.RA");
 	float dD = psMetadataLookupF32 (&status, sequence, "OFFSET.DEC");
-  
+      
 	int nR = psMetadataLookupS32 (&status, sequence, "OFFSET.NR");
 	int nD = psMetadataLookupS32 (&status, sequence, "OFFSET.ND");
-  
+      
 	// loop over the offset sequence
 	for (int iR = 0; iR < nR; iR++) {
@@ -50,12 +50,12 @@
 		float R = Ro + dR*(iR - 0.5*nR + 0.5) / cos (RAD_DEG*Do) / 3600.0;
 		float D = Do + dD*(iD - 0.5*nD + 0.5) / 3600.0;
-      
+              
 		// dither parameters
 		float dr = psMetadataLookupF32 (&status, sequence, "DITHER.RA");
 		float dd = psMetadataLookupF32 (&status, sequence, "DITHER.DEC");
-  
+          
 		int nr = psMetadataLookupS32 (&status, sequence, "DITHER.NR");
 		int nd = psMetadataLookupS32 (&status, sequence, "DITHER.ND");
-  
+          
 		// loop over the dither sequence
 		for (int ir = 0; ir < nr; ir++) {
@@ -65,5 +65,5 @@
 			float ra = R + dr*(ir - 0.5*nr + 0.5) / cos (RAD_DEG*D) / 3600.0;
 			float dec = D + dd*(id - 0.5*nd + 0.5) / 3600.0;
-	  
+	              
 			// rotation sequence parameters
 			float pos_min   = psMetadataLookupF32 (&status, sequence, "POS_MIN");
@@ -72,8 +72,8 @@
 			assert (pos_delta > 0.0);
 			assert (pos_max >= pos_min);
-	    
+	                
 			// loop over rotation sequence
 			for (float pos = pos_min; pos <= pos_max; pos += pos_delta) {
-	      
+	                  
 			    // define the output filename
 			    psString filename = NULL;
@@ -95,9 +95,9 @@
 			    psStringAppend (&command, " -dec %f", dec);
 			    psStringAppend (&command, " -pa %f", pos);
-                            psStringAppend (&command, " -obs_mode OBJECT.%s", (char *) filters->data[i]);
+			    psStringAppend (&command, " -obs_mode OBJECT.%s", (char *) filters->data[i]);
 
 			    double frnd = psRandomUniform(rng);
 			    float seeing = IQmin + (IQmax - IQmin)*frnd;
-	      
+	                  
 			    psStringAppend (&command, " -seeing %f", seeing);
 
@@ -106,13 +106,17 @@
 			    fprintf (simfile, "%s\n", command);
 			    psFree (command);
-			    
+			                
 			    // define the inject command
 			    // path should be dirname/filename
-			    command = psStringCopy (injectCommand);
-			    psStringAppend (&command, " %s*.fits",    filename);
-			    fprintf (inject, "%s\n", command);
-			    psFree (command);
+			    
+			    // we use the filename above (really the file root) to construct the filenames
+			    for (int i = 0; i < files->n; i++) {
+				command = psStringCopy (injectCommand);
+				psStringAppend (&command, " %s.%s", filename, (char *) files->data[i]);
+				fprintf (inject, "%s\n", command);
+				psFree (command);
+			    }
+
 			    psFree (filename);
-
 			    nImage ++;
 			}
