Index: trunk/psModules/src/config/pmConfig.c
===================================================================
--- trunk/psModules/src/config/pmConfig.c	(revision 18905)
+++ trunk/psModules/src/config/pmConfig.c	(revision 18908)
@@ -57,5 +57,4 @@
     psFree(config->site);
     psFree(config->system);
-    psFree(config->complete);
     psFree(config->files);
     psFree(config->camera);
@@ -139,5 +138,4 @@
     config->site = NULL;
     config->system = NULL;
-    config->complete = NULL;
     config->camera = NULL;
     config->cameraName = NULL;
@@ -232,7 +230,7 @@
 bool pmConfigFileRead(psMetadata **config, const char *name, const char *description)
 {
-    PS_ASSERT_PTR_NON_NULL(config, false);
-    PS_ASSERT_STRING_NON_EMPTY(name, false);
-    PS_ASSERT_STRING_NON_EMPTY(description, false);
+    assert(config);
+    assert(name);
+    assert(description);
 
     char *realName = NULL;
@@ -313,11 +311,8 @@
 }
 
-// Read a file into a metadataItem, if required
-static bool metadataItemReadFile(psMetadataItem *item, // Item into which to read file
-                                 const char *description // Description, for error messages
-    )
-{
-    assert(item);
-    assert(description);
+bool pmConfigFileIngest(psMetadataItem *item, const char *description)
+{
+    PS_ASSERT_METADATA_ITEM_NON_NULL(item, false);
+    PS_ASSERT_STRING_NON_EMPTY(description, false);
 
     if (item->type == PS_DATA_METADATA) {
@@ -357,5 +352,5 @@
     psMetadataItem *item;               // Item from iteration
     while ((item = psMetadataGetAndIncrement(iter))) {
-        if (!metadataItemReadFile(item, description)) {
+        if (!pmConfigFileIngest(item, description)) {
             psError(PM_ERR_CONFIG, false, "Unable to read %s %s.", description, item->name);
             psFree(iter);
@@ -400,23 +395,6 @@
     psMetadataItem *darkNorm = psMetadataLookup(camera, "DARK.NORM"); // The dark normalisation calibration
     if (darkNorm) {
-        if (darkNorm->type == PS_DATA_STRING) {
-            const char *darkNormName = darkNorm->data.str; // The file name
-            psTrace("config", 2, "Reading %s dark normalisation: %s\n", cameraName, darkNormName);
-            psMetadata *new = NULL;         // New metadata
-            if (!pmConfigFileRead(&new, darkNormName, "Dark normalisation")) {
-                psError(PM_ERR_CONFIG, false, "Trouble reading reading %s dark normalisation %s --- "
-                        "ignored.\n", cameraName, darkNormName);
-                psFree(new);
-                return false;
-            }
-
-            // Muck around under the hood to replace the filename with the metadata;
-            // don't try this at home, kids
-            darkNorm->type = PS_DATA_METADATA;
-            psFree(darkNorm->data.str);
-            darkNorm->data.md = new;
-        } else if (darkNorm->type != PS_DATA_METADATA) {
-            psWarning("DARK.NORM in camera %s is not of type STR or METADATA (%x)",
-                      cameraName, darkNorm->type);
+        if (!pmConfigFileIngest(darkNorm, "dark normalisation")) {
+            psWarning("Unable to ingest DARK.NORM in camera %s", cameraName);
         }
     } else {
@@ -505,21 +483,30 @@
 
     // read the SITE file
-    psString siteFile = psMetadataLookupStr(NULL, config->user, "SITE");
-    if (!pmConfigFileRead(&config->site, siteFile, "site")) {
+    psMetadataItem *siteItem = psMetadataLookup(config->user, "SITE");
+    if (!siteItem) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find SITE in user configuration.");
         psFree(config);
         return NULL;
     }
-
-    // load the SYSTEM file
-    psString systemFile = psMetadataLookupStr(NULL, config->user, "SYSTEM");
-    if (!pmConfigFileRead(&config->system, systemFile, "system")) {
+    if (!pmConfigFileIngest(siteItem, "site configuration")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read site configuration");
         psFree(config);
         return NULL;
     }
-
-    // interpolate USER, SITE and SYSTEM into the config->complete metadata
-    config->complete = psMetadataCopy (NULL,             config->user);
-    config->complete = psMetadataCopy (config->complete, config->site);
-    config->complete = psMetadataCopy (config->complete, config->system);
+    config->site = psMemIncrRefCounter(siteItem->data.md);
+
+    // load the SYSTEM file
+    psMetadataItem *systemItem = psMetadataLookup(config->user, "SYSTEM");
+    if (!systemItem) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to find SYSTEM in user configuration.");
+        psFree(config);
+        return NULL;
+    }
+    if (!pmConfigFileIngest(systemItem, "system configuration")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to read system configuration");
+        psFree(config);
+        return NULL;
+    }
+    config->system = psMemIncrRefCounter(systemItem->data.md);
 
     // Set LOG and TRACE options based on the user configuration.  These must be set AFTER
@@ -651,7 +638,6 @@
         // Initialise the psLib time handling
         // XXX is this still needed / desired?
-        psString timeName = psMetadataLookupStr(&mdok, config->complete, "TIME");
-        if (mdok && timeName)
-        {
+        psString timeName = psMetadataLookupStr(&mdok, config->system, "TIME");
+        if (mdok && timeName) {
             psTrace("psModules.config", 7, "Initialising psTime with file %s\n", timeName);
             psTimeInit(timeName);
@@ -671,6 +657,6 @@
             char *cameraName = argv[argNum]; // symbolic name of the camera
 
-            // look for the CAMERAS list in config->complete
-            psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
+            // look for the CAMERAS list in config->system
+            psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->system, "CAMERAS");
             if (!cameras) {
                 psError(PS_ERR_IO, false, "Unable to find CAMERAS in site configuration.\n");
@@ -718,5 +704,5 @@
                                   "Camera specified on command line", config->camera);
 
-            if (!pmConfigCameraSkycellVersion(config->complete, cameraName)) {
+            if (!pmConfigCameraSkycellVersion(config->system, cameraName)) {
                 psError(PS_ERR_UNKNOWN, false,
                         "Unable to generate skycell versions of specified camera %s.\n",
@@ -726,5 +712,5 @@
             }
 
-            if (!pmConfigCameraMosaickedVersions(config->complete, cameraName)) {
+            if (!pmConfigCameraMosaickedVersions(config->system, cameraName)) {
                 psError(PS_ERR_UNKNOWN, false,
                         "Unable to generate mosaicked versions of specified camera %s.\n",
@@ -739,5 +725,5 @@
     if (!config->camera && readCameraConfig) {
         bool mdok;                      // Status of MD lookup
-        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS"); // List of cameras
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->system, "CAMERAS"); // List of cameras
         if (!mdok || !cameras) {
             psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
@@ -773,10 +759,10 @@
         psFree(iter);
 
-        if (!pmConfigCameraSkycellVersionsAll(config->complete)) {
+        if (!pmConfigCameraSkycellVersionsAll(config->system)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to generate skycell versions of cameras.\n");
             psFree(config);
             return NULL;
         }
-        if (!pmConfigCameraMosaickedVersionsAll(config->complete)) {
+        if (!pmConfigCameraMosaickedVersionsAll(config->system)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to generate mosaicked versions of cameras.\n");
             psFree(config);
@@ -817,5 +803,5 @@
         psArgumentRemove(argNum, argc, argv);
 
-        psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS"); // List of cameras
+        psMetadata *cameras = psMetadataLookupMetadata(NULL, config->system, "CAMERAS"); // List of cameras
         if (!cameras) {
             psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find CAMERAS in the site configuration.\n");
@@ -865,5 +851,5 @@
         } else {
             char *dbserver = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBSERVER", PS_META_REPLACE,
+            if (!psMetadataAddStr(config->user, PS_LIST_TAIL, "DBSERVER", PS_META_REPLACE,
                                   NULL, dbserver)) {
                 psWarning("Failed to overwrite .ipprc DBSERVER value");
@@ -881,5 +867,5 @@
         } else {
             char *dbname = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBNAME", PS_META_REPLACE, NULL, dbname)) {
+            if (!psMetadataAddStr(config->user, PS_LIST_TAIL, "DBNAME", PS_META_REPLACE, NULL, dbname)) {
                 psWarning("Failed to overwrite .ipprc DBNAME value");
             }
@@ -896,5 +882,5 @@
         } else {
             char *dbuser = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBUSER", PS_META_REPLACE, NULL, dbuser)) {
+            if (!psMetadataAddStr(config->user, PS_LIST_TAIL, "DBUSER", PS_META_REPLACE, NULL, dbuser)) {
                 psWarning("Failed to overwrite .ipprc DBUSER value");
             }
@@ -911,5 +897,5 @@
         } else {
             char *dbpassword = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBPASSWORD", PS_META_REPLACE,
+            if (!psMetadataAddStr(config->user, PS_LIST_TAIL, "DBPASSWORD", PS_META_REPLACE,
                                   NULL, dbpassword)) {
                 psWarning("Failed to overwrite .ipprc DBPASSWORD value");
@@ -927,5 +913,5 @@
         } else {
             char *dbport = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddS32(config->complete, PS_LIST_TAIL, "DBPORT", PS_META_REPLACE, NULL,
+            if (!psMetadataAddS32(config->user, PS_LIST_TAIL, "DBPORT", PS_META_REPLACE, NULL,
                                   (psS32)atoi(dbport))) {
                 psWarning("Failed to overwrite .ipprc DBPORT value");
@@ -1113,5 +1099,5 @@
 
         bool mdok;                      // Metadata lookup status
-        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->system, "CAMERAS");
         if (! mdok || !cameras) {
             psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
@@ -1183,5 +1169,5 @@
     char *testName = NULL;
 
-    psMetadata *cameras = psMetadataLookupMetadata (NULL, config->complete, "CAMERAS");
+    psMetadata *cameras = psMetadataLookupMetadata (NULL, config->system, "CAMERAS");
     psAssert (cameras, "missing CAMERAS in complete metadata");
 
@@ -1263,5 +1249,5 @@
     PS_ASSERT_STRING_NON_EMPTY(cameraName, NULL);
 
-    psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS");
+    psMetadata *cameras = psMetadataLookupMetadata(NULL, config->system, "CAMERAS");
     if (!cameras) {
         psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
@@ -1269,19 +1255,11 @@
     }
 
-    char *cameraPath = psMetadataLookupStr(NULL, cameras, cameraName);
-    if (!cameraPath) {
-        psError(PS_ERR_IO, true, "Unable to find requested CAMERA in the configuration.");
+    psMetadataItem *item = psMetadataLookup(cameras, cameraName); // Item with camera of interest
+    if (!pmConfigFileIngest(item, "camera configuration")) {
+        psError(PS_ERR_UNKNOWN, false, "Unable to ingest camera configuration.");
         return NULL;
     }
 
-    psMetadata *camera = NULL; // Camera to test against what we've got:
-
-    if (!pmConfigFileRead(&camera, cameraPath, cameraName)) {
-        psWarning("Trouble reading reading camera configuration %s", cameraName);
-        psFree(camera);
-        return NULL;
-    }
-
-    return camera;
+    return psMemIncrRefCounter(item->data.md);
 }
 
@@ -1289,5 +1267,5 @@
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
-    PS_ASSERT_PTR_NON_NULL(config->complete, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->user, NULL);
 
     #ifndef HAVE_PSDB
@@ -1310,9 +1288,9 @@
 
     // XXX leaky strings
-    psString dbServer = psMetadataLookupStr(&mdStatus01, config->complete, "DBSERVER");
-    psString dbUsername = psMetadataLookupStr(&mdStatus02, config->complete, "DBUSER");
-    psString dbPassword = psMetadataLookupStr(&mdStatus03, config->complete, "DBPASSWORD");
-    psString dbName = psMetadataLookupStr(&mdStatus04, config->complete, "DBNAME");
-    psS32 dbPort = psMetadataLookupS32(&mdStatus05, config->complete, "DBPORT");
+    psString dbServer = psMetadataLookupStr(&mdStatus01, config->user, "DBSERVER");
+    psString dbUsername = psMetadataLookupStr(&mdStatus02, config->user, "DBUSER");
+    psString dbPassword = psMetadataLookupStr(&mdStatus03, config->user, "DBPASSWORD");
+    psString dbName = psMetadataLookupStr(&mdStatus04, config->user, "DBNAME");
+    psS32 dbPort = psMetadataLookupS32(&mdStatus05, config->user, "DBPORT");
     if (!mdStatus05) {
         dbPort = 0;
@@ -1527,11 +1505,11 @@
     // replace path://PATH with matched datapath
     if (!strncasecmp(filename, "path://", strlen("path://"))) {
-        PS_ASSERT_METADATA_NON_NULL(config->complete, NULL);
+        PS_ASSERT_METADATA_NON_NULL(config->site, NULL);
 
         psString newName = psStringCopy(filename);
 
         // filename should be of the form: path://PATH/rest/of/file
-        // replace PATH with matching name from config->complete:DATAPATH
-        psMetadata *datapath = psMetadataLookupPtr (NULL, config->complete, "DATAPATH");
+        // replace PATH with matching name from config->site:DATAPATH
+        psMetadata *datapath = psMetadataLookupPtr (NULL, config->site, "DATAPATH");
         if (datapath == NULL) {
             psError(PS_ERR_UNKNOWN, true, "DATAPATH is not defined in config.site");
@@ -1586,5 +1564,5 @@
         // if env isn't set, check the config system
         if (!neb_server) {
-            neb_server = psMetadataLookupStr(&status, config->complete, "NEB_SERVER");
+            neb_server = psMetadataLookupStr(&status, config->site, "NEB_SERVER");
             if (!status) {
                 psError(PM_ERR_CONFIG, true, "failed to lookup config value for NEB_SERVER.");
@@ -1662,5 +1640,5 @@
     }
 
-    if (!metadataItemReadFile(item, "file rules ")) {
+    if (!pmConfigFileIngest(item, "file rules ")) {
         psError(PM_ERR_CONFIG, false, "Unable to read file rules for camera.");
         return NULL;
@@ -1695,5 +1673,5 @@
     }
 
-    if (!metadataItemReadFile(item, "FITS Types")) {
+    if (!pmConfigFileIngest(item, "FITS Types")) {
         psError(PM_ERR_CONFIG, false, "Unable to read fits types for camera.");
         return NULL;
Index: trunk/psModules/src/config/pmConfig.h
===================================================================
--- trunk/psModules/src/config/pmConfig.h	(revision 18905)
+++ trunk/psModules/src/config/pmConfig.h	(revision 18908)
@@ -5,6 +5,6 @@
  *  @author Eugene Magnier, IfA
  *
- *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-08-05 02:16:06 $
+ *  @version $Revision: 1.40 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-08-05 03:45:56 $
  *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -40,5 +40,4 @@
     psMetadata *site;                   ///< Site configuration
     psMetadata *system;                 ///< System configuration
-    psMetadata *complete;               ///< Full merged configuration
     psMetadata *camera;                 ///< Camera specification
     psString cameraName;                ///< Camera name
@@ -86,10 +85,18 @@
 /// Read a configuration file
 ///
-/// Read a metadata configuration file into the supplied metadata.  Produce an error and return false if
-/// there's a problem.
+/// Read a metadata configuration file into the supplied metadata.  Produce an error and
+/// return false if there's a problem.
 bool pmConfigFileRead(psMetadata **config, ///< Config to output
                       const char *name, ///< Name of file
                       const char *description ///< Description of file
-                     );
+    );
+
+/// Ingest a configuration file
+///
+/// Ingest a metadata configuration file into the supplied metadata item, if required.  Produce an error and
+/// return false if there's a problem.
+bool pmConfigFileIngest(psMetadataItem *item, // Item into which to read file
+                        const char *description // Description, for error messages
+    );
 
 /// Validate a header against the camera format
Index: trunk/psModules/src/config/pmConfigCommand.c
===================================================================
--- trunk/psModules/src/config/pmConfigCommand.c	(revision 18905)
+++ trunk/psModules/src/config/pmConfigCommand.c	(revision 18908)
@@ -13,23 +13,23 @@
     PS_ASSERT_PTR_NON_NULL(command, false);
     PS_ASSERT_PTR_NON_NULL(config, false);
-    PS_ASSERT_PTR_NON_NULL(config->complete, false);
+    PS_ASSERT_PTR_NON_NULL(config->user, false);
 
     bool mdok;                          // Status of MD lookup
-    const char *dbserver = psMetadataLookupStr(&mdok, config->complete, "DBSERVER"); // Database server
+    const char *dbserver = psMetadataLookupStr(&mdok, config->user, "DBSERVER"); // Database server
     if (!mdok || strlen(dbserver) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBSERVER in site configuration.\n");
         return false;
     }
-    const char *dbname = psMetadataLookupStr(&mdok, config->complete, "DBNAME"); // Database name
+    const char *dbname = psMetadataLookupStr(&mdok, config->user, "DBNAME"); // Database name
     if (!mdok || strlen(dbname) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBNAME in site configuration.\n");
         return false;
     }
-    const char *dbuser = psMetadataLookupStr(&mdok, config->complete, "DBUSER"); // Database user
+    const char *dbuser = psMetadataLookupStr(&mdok, config->user, "DBUSER"); // Database user
     if (!mdok || strlen(dbuser) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBUSER in site configuration.\n");
         return false;
     }
-    const char *dbpassword = psMetadataLookupStr(&mdok, config->complete, "DBPASSWORD"); // Database password
+    const char *dbpassword = psMetadataLookupStr(&mdok, config->user, "DBPASSWORD"); // Database password
     if (!mdok || strlen(dbpassword) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBPASSWORD in site configuration.\n");
Index: trunk/psModules/src/config/pmConfigDump.c
===================================================================
--- trunk/psModules/src/config/pmConfigDump.c	(revision 18905)
+++ trunk/psModules/src/config/pmConfigDump.c	(revision 18908)
@@ -64,5 +64,5 @@
       PS_ASSERT_PTR_NON_NULL(config, false);
 
-      psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS"); // Known cameras
+      psMetadata *cameras = psMetadataLookupMetadata(NULL, config->system, "CAMERAS"); // Known cameras
       if (!cameras) {
           psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find CAMERAS in the system configuration.\n");
@@ -146,5 +146,5 @@
     }
 
-    if (!psMetadataConfigWrite(config->complete, filename)) {
+    if (!psMetadataConfigWrite(config->user, filename)) {
         psError(PS_ERR_IO, false, "Unable to dump configuration to %s", filename);
         psFree(filename);
Index: trunk/psModules/src/config/pmConfigRecipes.c
===================================================================
--- trunk/psModules/src/config/pmConfigRecipes.c	(revision 18905)
+++ trunk/psModules/src/config/pmConfigRecipes.c	(revision 18908)
@@ -28,5 +28,6 @@
     if (!options) {
         options = psMetadataAlloc ();
-        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "", options);
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "",
+                                    options);
         assert (success); // type mismatch : OPTIONS already defined but wrong type
         psFree (options); // drop extra reference
@@ -47,5 +48,5 @@
 
 // this function may be called several times.  it attempts to load the recipe data from one of three
-// locations: config->complete, config->camera, and argv.  We cannot read the recipes from
+// locations: config->system, config->camera, and argv.  We cannot read the recipes from
 // config->camera until a camera has been read BUT, the argv recipes must override the camera and
 // system recipes.  This command strips the argv elements it uses from the argv list.
@@ -60,9 +61,9 @@
 
     // Read the recipe file names from the system configuration and camera configuration
-    // It is an error for config->complete:recipes not to exist.  all programs install their
+    // It is an error for config->system:recipes not to exist.  all programs install their
     // master recipe files in the system:recipe location when they are built.
-    psAssert (config->complete, "base config data defined");
+    psAssert(config->system, "base config data defined");
     if (source & PM_RECIPE_SOURCE_SYSTEM) {
-        if (!loadRecipeSystem(&status, config, config->complete)) {
+        if (!loadRecipeSystem(&status, config, config->system)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from system config");
             return false;
@@ -75,5 +76,6 @@
     // for an identified camera (in pmConfigCameraFormatFromHeader).  the second
     // set should not override the first set
-    if (config->camera && (source & PM_RECIPE_SOURCE_CAMERA) && !(config->recipesRead & PM_RECIPE_SOURCE_CAMERA)) {
+    if (config->camera && (source & PM_RECIPE_SOURCE_CAMERA) &&
+        !(config->recipesRead & PM_RECIPE_SOURCE_CAMERA)) {
         if (!loadRecipeCamera(&status, config, config->camera)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from camera config");
@@ -87,8 +89,9 @@
     }
 
-    // merge camera and sytem recipes, apply recipes loaded into config->arguments based on command-line arguments
+    // merge camera and sytem recipes, apply recipes loaded into config->arguments based on command-line
+    // arguments
     if (config->arguments && (source & PM_RECIPE_SOURCE_CL)) {
 
-	// update the system-level recipes with the symbolically-defined recipes 
+        // update the system-level recipes with the symbolically-defined recipes
         if (!loadRecipeSymbols(&status, config, PM_RECIPE_SOURCE_SYSTEM)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
@@ -101,12 +104,12 @@
         }
 
-	// merge the SYSTEM and CAMERA recipes
+        // merge the SYSTEM and CAMERA recipes
         if (!mergeRecipeCamera(&status, config)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
             return false;
         }
-	psLogMsg ("psModules.config", PS_LOG_DETAIL, "merged camera recipes with system recipes");
-
-	// load recipe-files specified on the command line
+        psLogMsg ("psModules.config", PS_LOG_DETAIL, "merged camera recipes with system recipes");
+
+        // load recipe-files specified on the command line
         if (!loadRecipeFromArguments(&status, config)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from command-line arguments");
@@ -119,5 +122,5 @@
         }
 
-	// update the system-level recipes with the symbolically-defined recipes 
+        // update the system-level recipes with the symbolically-defined recipes
         if (!loadRecipeSymbols(&status, config, PM_RECIPE_SOURCE_CAMERA)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
@@ -130,5 +133,5 @@
         }
 
-	// override any specific values with values from the command line
+        // override any specific values with values from the command line
         if (!loadRecipeOptions(&status, config)) {
             psError(PS_ERR_IO, false, "Failed to read recipes from symbolic references");
@@ -155,5 +158,6 @@
     if (!options) {
         options = psMetadataAlloc();
-        success = psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA, "Command-line options specified with -D", options);
+        success = psMetadataAddPtr(config->arguments, PS_LIST_TAIL, "OPTIONS",  PS_DATA_METADATA,
+                                   "Command-line options specified with -D", options);
         assert (success); // type mismatch : OPTIONS already defined but wrong type
         psFree (options); // drop extra reference
@@ -178,5 +182,6 @@
             recipeName = config->defaultRecipe;
             if (!config->defaultRecipe) {
-                psError(PS_ERR_IO, true, "syntax error in parameter: no default recipe available; must specify recipe");
+                psError(PS_ERR_IO, true,
+                        "syntax error in parameter: no default recipe available; must specify recipe");
                 return false;
             }
@@ -242,5 +247,6 @@
     if (!recipes) {
         recipes = psMetadataAlloc();
-        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "", recipes);
+        success = psMetadataAddPtr (config->arguments, PS_LIST_TAIL, "RECIPES",  PS_DATA_METADATA, "",
+                                    recipes);
         assert (success);
         psFree (recipes);
@@ -298,5 +304,6 @@
         // Assume it's a symbolic reference to something that's not yet read in.
         // it will be loaded later by pmConfigReadRecipes with option CL
-        psMetadataAddStr(config->recipeSymbols, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL, recipeSource);
+        psMetadataAddStr(config->recipeSymbols, PS_LIST_TAIL, recipeName, PS_META_REPLACE, NULL,
+                         recipeSource);
 
         psTrace ("psModules.config", 3, "read recipe %s from %s", recipeName, recipeSource);
@@ -319,5 +326,6 @@
 
     if (!source) {
-        psError(PS_ERR_IO, true, "The system configuration has not been read --- cannot read recipes from this location.\n");
+        psError(PS_ERR_IO, true,
+                "The system configuration has not been read --- cannot read recipes from this location.\n");
         config->recipesRead &= ~PM_RECIPE_SOURCE_SYSTEM;
         return false;
@@ -334,24 +342,16 @@
     // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
     psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
-    psMetadataItem *fileItem = NULL;    // MD item containing the filename, from recipe iteration
-    while ((fileItem = psMetadataGetAndIncrement(recipesIter))) {
-        char *recipeName = fileItem->name;
-        char *recipeFile = fileItem->data.str;
-
-        // type mismatch is a serious error
-        if (fileItem->type != PS_DATA_STRING) {
-            psAbort("%s in system configuration RECIPES is not of type STR", recipeName);
-        }
-
-        // Read the recipe file. if we fail on a file, give a warning, but continue
-        psMetadata *recipe = NULL;
-        if (!pmConfigFileRead(&recipe, recipeFile, "recipe")) {
-            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in system configuration\n", recipeFile);
-            return false;
-        }
-
-        // and the contents of this recipe file to config->recipes
-        psMetadataAdd(config->recipes, PS_LIST_TAIL, fileItem->name, PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
-        psFree(recipe);  // Drop reference
+    psMetadataItem *item = NULL;        // MD item containing the filename, from recipe iteration
+    while ((item = psMetadataGetAndIncrement(recipesIter))) {
+        if (!pmConfigFileIngest(item, "recipe")) {
+            psError(PS_ERR_IO, false, "Failed to read recipe %s listed in system configuration",
+                    item->name);
+            psFree(recipesIter);
+            return false;
+        }
+
+        // add the contents of this recipe file to config->recipes
+        psMetadataAdd(config->recipes, PS_LIST_TAIL, item->name, PS_DATA_METADATA | PS_META_REPLACE,
+                      item->comment, item->data.md);
     }
     psFree(recipesIter);
@@ -375,5 +375,6 @@
 
     if (!source) {
-        psError(PS_ERR_IO, true, "The camera configuration has not been read --- cannot read recipes from this location.\n");
+        psError(PS_ERR_IO, true,
+                "The camera configuration has not been read --- cannot read recipes from this location.\n");
         config->recipesRead &= ~PM_RECIPE_SOURCE_CAMERA;
         return false;
@@ -392,22 +393,13 @@
     // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
     psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
-    psMetadataItem *fileItem = NULL;    // MD item containing the filename, from recipe iteration
-    while ((fileItem = psMetadataGetAndIncrement(recipesIter))) {
-        char *recipeName = fileItem->name;
-        char *recipeFile = fileItem->data.str;
-
-        psTrace("psModules.config", 3, "loading %s from %s within camera configuration.\n", recipeName, recipeFile);
-
-        // type mismatch is a serious error
-        if (fileItem->type != PS_DATA_STRING) {
-            psAbort("%s in camera configuration RECIPES is not of type STR", recipeName);
-        }
-
-        // Read the recipe file. if we fail on a file, give a warning, but continue
-        psMetadata *recipe = NULL;
-        if (!pmConfigFileRead(&recipe, recipeFile, "recipe")) {
-            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in camera configuration\n", recipeFile);
-            return false;
-        }
+    psMetadataItem *item = NULL;    // MD item containing the filename, from recipe iteration
+    while ((item = psMetadataGetAndIncrement(recipesIter))) {
+        if (!pmConfigFileIngest(item, "recipe")) {
+            psError(PS_ERR_IO, false, "Failed to read recipe %s listed in camera configuration",
+                    item->name);
+            return false;
+        }
+        const char *recipeName = item->name; // Name of the recipe
+        psMetadata *recipe = item->data.md; // The recipe
 
         // the named recipe must exist at the system level
@@ -415,11 +407,10 @@
         if (!current) {
             psError(PS_ERR_IO, false, "Failed to find recipe for %s in master recipe list", recipeName);
-            psFree(recipe);  // Drop reference
             return false;
         }
 
         // add the contents of this recipe file to config->recipesCamera
-        psMetadataAdd(config->recipesCamera, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE, fileItem->comment, recipe);
-        psFree(recipe);  // Drop reference
+        psMetadataAdd(config->recipesCamera, PS_LIST_TAIL, recipeName, PS_DATA_METADATA | PS_META_REPLACE,
+                      item->comment, recipe);
     }
     psFree(recipesIter);
@@ -441,5 +432,5 @@
     // We could use psMetadataCopy for this, but it's better to check that everything's of the correct type.
     // If it's not of the correct type, we can tell the user which file it's in, so they can find it easier.
-    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipesCamera, PS_LIST_HEAD, NULL); // Iterator
+    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(config->recipesCamera, PS_LIST_HEAD, NULL);
     psMetadataItem *folderItem = NULL;    // MD item containing the filename, from recipe iteration
     while ((folderItem = psMetadataGetAndIncrement(recipesIter))) {
@@ -459,8 +450,8 @@
 
         // update the contents of this recipe from the one on config->recipesCamera
-	if (!psMetadataUpdate(current, recipe)) {
-	    psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
-	    return false;
-	}
+        if (!psMetadataUpdate(current, recipe)) {
+            psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", recipeName);
+            return false;
+        }
     }
     psFree(recipesIter);
@@ -552,23 +543,23 @@
 
         // search for sourceName in config->recipes (folder name is targetName)
-	psMetadata *folder = psMetadataLookupMetadata(&found, config->recipes, targetName);
-	psMetadata *sourceMD = psMetadataLookupMetadata(&found, folder, sourceName);
-
-	// if we find the desired symbolic name at this level, set the item comment to say "FOUND"
+        psMetadata *folder = psMetadataLookupMetadata(&found, config->recipes, targetName);
+        psMetadata *sourceMD = psMetadataLookupMetadata(&found, folder, sourceName);
+
+        // if we find the desired symbolic name at this level, set the item comment to say "FOUND"
         if (sourceMD) {
-	  if (!psMetadataUpdate(targetMD, sourceMD)) {
+          if (!psMetadataUpdate(targetMD, sourceMD)) {
             psError(PS_ERR_IO, false, "Failed to update recipe for %s from camera recipe", targetName);
             return false;
-	  }
-	  psStringAppend (&item->comment, "(FOUND)");
-	}	  
-
-	// if we have not found it by the camera level, we have a problem
-	if (source == PM_RECIPE_SOURCE_CAMERA) {
-	  if (strstr (item->comment, "(FOUND)") == NULL) {
-	    psError(PS_ERR_IO, false, "Selected symbolic name %s does not exist in recipes", sourceName);
-	    return false;
-	  }
-	}
+          }
+          psStringAppend (&item->comment, "(FOUND)");
+        }
+
+        // if we have not found it by the camera level, we have a problem
+        if (source == PM_RECIPE_SOURCE_CAMERA) {
+          if (strstr (item->comment, "(FOUND)") == NULL) {
+            psError(PS_ERR_IO, false, "Selected symbolic name %s does not exist in recipes", sourceName);
+            return false;
+          }
+        }
     }
     psFree(iter);
@@ -594,5 +585,5 @@
     }
 
-    psMetadata *recipes = psMetadataLookupMetadata(&found, config->arguments, "OPTIONS"); // The list of recipes
+    psMetadata *recipes = psMetadataLookupMetadata(&found, config->arguments, "OPTIONS"); // List of recipes
     if (!recipes) {
         psTrace("psModules.config", 4, "no OPTIONS in config->arguments, nothing to read here");
