Index: trunk/ppNorm/src/ppNormCalc.c
===================================================================
--- trunk/ppNorm/src/ppNormCalc.c	(revision 8785)
+++ trunk/ppNorm/src/ppNormCalc.c	(revision 8999)
@@ -7,4 +7,16 @@
 #include <psmodules.h>
 
+void helpAndDie(const char *programName)
+{
+    printf("Calculate normalisation for flat fields.\n\n"
+           "Usage: %s [IN.mdc [OUT.mdc]]\n\n"
+           "where IN.mdc is a metadata config file containing the background\n"
+           "      value for each component of each exposure;\n"
+           "and   OUT.mdc is a metadata config file containing the output\n"
+           "      normalisation factors.\n"
+           "\n", programName);
+    exit(EXIT_FAILURE);
+}
+
 
 int main(int argc, char *argv[])
@@ -14,16 +26,39 @@
     psFree(config);
 
-    if (argc != 2) {
-        printf("Calculate normalisation for flat fields.\n\n"
-               "Usage: %s IN.mdc\n\n"
-               "where IN.mdc is a metadata config file containing the background\n"
-               "value for each component of each exposure.\n\n", argv[0]);
-        exit(EXIT_FAILURE);
+    if (argc > 3 ||
+        psArgumentGet(argc, argv, "-h") ||
+        psArgumentGet(argc, argv, "-help") ||
+        psArgumentGet(argc, argv, "--help") ||
+        psArgumentGet(argc, argv, "-?")) {
+        helpAndDie(argv[0]);
+    }
+
+    FILE *inFile = stdin;               // Input file stream
+    FILE *outFile = stdout;             // Output file stream
+
+    if (argc >= 2) {
+        inFile = fopen(argv[1], "r");
+        if (!inFile) {
+            psError(PS_ERR_IO, true, "Unable to open input file: %s\n\n", argv[1]);
+            helpAndDie(argv[0]);
+        }
+    }
+    if (argc == 3) {
+        outFile = fopen(argv[2], "w");
+        if (!outFile) {
+            psError(PS_ERR_IO, true, "Unable to open output file: %s\n\n", argv[2]);
+            helpAndDie(argv[0]);
+        }
+    }
+
+    psString inputMDC = psSlurpFile(inFile); // Input metadata config stuff
+    if (argc >= 2) {
+        fclose(inFile);
     }
 
     psU32 badLines = 0;                   // Number of bad lines
-    psMetadata *exposures = psMetadataConfigRead(NULL, &badLines, argv[1], false); // Exposure statistics
+    psMetadata *exposures = psMetadataConfigParse(NULL, &badLines, inputMDC, false); // Exposure statistics
     if (badLines > 0) {
-        psLogMsg("ppNormCalc", PS_LOG_WARN, "%d bad lines found when reading %s\n", badLines, argv[1]);
+        psWarning("%d bad lines found when reading input\n", badLines);
     }
 
@@ -97,7 +132,10 @@
     psFree(compsIter);
     psString outputString = psMetadataConfigFormat(outputMD);
-    printf("%s", outputString);
+    fprintf(outFile, "%s", outputString);
     psFree(outputString);
     psFree(outputMD);
+    if (argc == 3) {
+        fclose(outFile);
+    }
 
     // Clean up
