Index: trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 16608)
+++ trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 16611)
@@ -155,7 +155,7 @@
     } else {
         bool mdok;                      // Status of MD lookup
-        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS"); // Known cameras
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS"); // Known cameras
         if (!mdok || !cameras) {
-            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
             return NULL;
         }
@@ -163,5 +163,5 @@
         if (!mdok || !camera) {
             psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find automatically generated "
-                    "camera configuration %s in site configuration.\n", cameraName);
+                    "camera configuration %s in system configuration.\n", cameraName);
             return NULL;
         }
Index: trunk/psModules/src/config/pmConfig.c
===================================================================
--- trunk/psModules/src/config/pmConfig.c	(revision 16608)
+++ trunk/psModules/src/config/pmConfig.c	(revision 16611)
@@ -34,6 +34,6 @@
 #endif // ifdef HAVE_NEBCLIENT
 
-#define PS_SITE "PS_SITE"         // Name of the environment variable containing the site config file
-#define PS_DEFAULT_SITE ".ipprc"  // Default site config file
+#define IPPRC_ENV "IPPRC"        // Name of the environment variable containing the top-level config file
+#define IPPRC_FILE ".ipprc"      // Default top-level config file
 
 #define DEFAULT_LOG STDERR_FILENO       // Default file descriptor for log messages
@@ -52,5 +52,8 @@
 static void configFree(pmConfig *config)
 {
+    psFree(config->user);
     psFree(config->site);
+    psFree(config->system);
+    psFree(config->complete);
     psFree(config->files);
     psFree(config->camera);
@@ -80,5 +83,8 @@
 
     // Initialise
+    config->user = NULL;
     config->site = NULL;
+    config->system = NULL;
+    config->complete = NULL;
     config->camera = NULL;
     config->cameraName = NULL;
@@ -145,5 +151,7 @@
     PS_ASSERT_STRING_NON_EMPTY(path,);
 
-    pmConfigDone();
+    assert (configPath == NULL);
+    // XXX why was this being called?  pmConfigSet should only be called once...
+    // pmConfigDone();
 
     psList *list = psStringSplit(path, ":", false);
@@ -159,5 +167,7 @@
 void pmConfigDone(void)
 {
-    psFree(configPath);
+    if (configPath) { 
+	psFree(configPath);
+    }
     configPath = NULL;
 
@@ -380,25 +390,20 @@
     config->defaultRecipe = defaultRecipe;
 
-    //
-    // The following section of code attempts to determine which file is
-    // the configuration file.  At the end of this code block, the siteName
+    // The following section of code attempts to determine which file to use as the
+    // top-level the configuration file.  At the end of this code block, the configFile
     // variable will contain the name of the configuration file.
-    //
-    char *siteName = NULL;
+
+    char *configFile = NULL;
     //
     // First, try command line
     //
-    psS32 argNum = psArgumentGet(*argc, argv, "-site");
+    psS32 argNum = psArgumentGet(*argc, argv, "-ipprc");
     if (argNum != 0) {
-        //
-        // We remove the "-site" argument from argv.  Then
-        // we look for the next argument, which should be the filename, and
-        // remove it as well.
-        //
+        // remove the "-ipprc" argument from argv, check and remove filename
         psArgumentRemove(argNum, argc, argv);
         if (argNum >= *argc) {
-            psWarning("-site command-line switch provided without the required filename --- ignored.\n");
+            psWarning("-ipprc command-line switch provided without the required filename --- ignored.\n");
         } else {
-            siteName = psStringCopy(argv[argNum]);
+            configFile = psStringCopy(argv[argNum]);
             psArgumentRemove(argNum, argc, argv);
         }
@@ -407,8 +412,8 @@
     // Next, try environment variable
     //
-    if (!siteName) {
-        siteName = getenv(PS_SITE);
-        if (siteName) {
-            siteName = psStringCopy (siteName);
+    if (!configFile) {
+        configFile = getenv(IPPRC_ENV);
+        if (configFile) {
+            configFile = psStringCopy (configFile);
         }
     }
@@ -417,35 +422,53 @@
     // Last chance is ~/.ipprc
     //
-    if (!siteName) {
+    if (!configFile) {
         char *home = getenv("HOME");
-        siteName = psStringCopy(home);
-        psStringAppend(&siteName, "/%s", PS_DEFAULT_SITE);
-    }
-
+        configFile = psStringCopy(home);
+        psStringAppend(&configFile, "/%s", IPPRC_FILE);
+    }
 
     // We have the configuration filename; now we read and parse the config
-    // file and store in psMetadata struct site.
-    //
-
-    if (!pmConfigFileRead(&config->site, siteName, "site")) {
+    // file and store in psMetadata struct user.
+    // XXX move this section to pmConfigReadUser.c ?
+
+    if (!pmConfigFileRead(&config->user, configFile, "user")) {
         psFree(config);
         return NULL;
     }
 
-    // Set options based on the site configuration.
+    // XXX why was this being called here?  Is someone calling pmConfigRead multiple times?
+    // pmConfigDone();
+    assert (configPath == NULL);  
+
+    // define the config-file search path (configPath).  
+    psString path = psMetadataLookupStr(NULL, config->user, "PATH");
+    pmConfigSet (path);
+
+    // read the SITE file
+    psString siteFile = psMetadataLookupStr(NULL, config->user, "SITE");
+    if (!pmConfigFileRead(&config->site, siteFile, "site")) {
+        psFree(config);
+        return NULL;
+    }
+
+    // load the SYSTEM file
+    psString systemFile = psMetadataLookupStr(NULL, config->user, "SYSTEM");
+    if (!pmConfigFileRead(&config->system, systemFile, "system")) {
+        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);
+
+    // Set LOG and TRACE options based on the user configuration.  These must be set AFTER
+    // the SITE and SYSTEM config files are read so path:// entries here can be resolved.
     {
         bool mdok = true;   // Status of MD lookup result
 
-        // Initialise the psLib time handling
-        psString timeName = psMetadataLookupStr(&mdok, config->site, "TIME");
-        if (mdok && timeName)
-        {
-            psTrace("psModules.config", 7, "Initialising psTime with file %s\n", timeName);
-            psTimeInit(timeName);
-        }
-
-
         // Set logging level
-        int logLevel = psMetadataLookupS32(&mdok, config->site, "LOGLEVEL");
+        int logLevel = psMetadataLookupS32(&mdok, config->user, "LOGLEVEL");
         if (mdok && logLevel >= 0)
         {
@@ -456,5 +479,5 @@
 
         // Set logging format
-        psString logFormat = psMetadataLookupStr(&mdok, config->site, "LOGFORMAT");
+        psString logFormat = psMetadataLookupStr(&mdok, config->user, "LOGFORMAT");
         if (mdok && logFormat)
         {
@@ -463,5 +486,5 @@
         }
 
-        // Set logging destination first from command line, second from site configuration
+        // Set logging destination first from command line, second from user configuration
         psString logDest = NULL;        // Logging destination
         argNum = psArgumentGet(*argc, argv, "-log");
@@ -477,5 +500,5 @@
         }
         if (!logDest) {
-            logDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->site, "LOGDEST"));
+            logDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->user, "LOGDEST"));
         }
         if (logDest) {
@@ -497,5 +520,5 @@
 
         // Set trace levels
-        psMetadata *trace = psMetadataLookupMetadata(&mdok, config->site, "TRACE");
+        psMetadata *trace = psMetadataLookupMetadata(&mdok, config->user, "TRACE");
         if (mdok && trace) {
             psMetadataIterator *traceIter = psMetadataIteratorAlloc(trace, PS_LIST_HEAD, NULL); // Iterator
@@ -515,5 +538,5 @@
 
         // Set trace formats
-        psString traceFormat = psMetadataLookupStr(&mdok, config->site, "TRACEFORMAT");
+        psString traceFormat = psMetadataLookupStr(&mdok, config->user, "TRACEFORMAT");
         if (mdok && traceFormat) {
             psTrace("psModules.config", 7, "Setting trace format to %s\n", traceFormat);
@@ -535,5 +558,5 @@
         }
         if (!traceDest) {
-            traceDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->site, "TRACEDEST"));
+            traceDest = psMemIncrRefCounter(psMetadataLookupStr(&mdok, config->user, "TRACEDEST"));
         }
         if (traceDest) {
@@ -563,31 +586,20 @@
     }
 
-    // define the config-file search path (configPath).  Ensure that
-    // it contains the directory where we found the config file in
-    // the first place
-    if (configPath) {
-        pmConfigDone();
-    }
-
-    psString siteNameDir = psStringCopy(dirname(siteName));
-    psFree(siteName);
-
-    psString path = psMetadataLookupStr(NULL, config->site, "PATH");
-    psString newPath = NULL;            // New path
-    // The following gymnastics with 'newPath' are required to avoid changing the pointer out from under the
-    // psMetadataItem on which 'path' sits (leading to memory corruption because it no longer points to valid
-    // memory).
-    if (path) {
-        psStringAppend(&newPath, "%s:%s", path, siteNameDir);
-    } else {
-        newPath = psMemIncrRefCounter(siteNameDir);
-    }
-    psFree(siteNameDir);
-    pmConfigSet(newPath);
-    psFree(newPath);
+    // XXX read TIME from SITE (or system?)
+    { 
+	bool mdok = true;
+
+        // Initialise the psLib time handling
+	// XXX is this still needed / desired?
+        psString timeName = psMetadataLookupStr(&mdok, config->complete, "TIME");
+        if (mdok && timeName)
+        {
+            psTrace("psModules.config", 7, "Initialising psTime with file %s\n", timeName);
+            psTimeInit(timeName);
+        }
+    }
 
     // Next, we do a similar thing for the camera configuration file.  The
     // file is read and parsed into psMetadata struct "camera".
-    //
     argNum = psArgumentGet(*argc, argv, "-camera");
     if (argNum > 0) {
@@ -600,6 +612,6 @@
             char *cameraName = argv[argNum]; // symbolic name of the camera
 
-            // look for the CAMERAS list in config->site
-            psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS");
+            // look for the CAMERAS list in config->complete
+            psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
             if (!cameras) {
                 psError(PS_ERR_IO, false, "Unable to find CAMERAS in site configuration.\n");
@@ -647,5 +659,5 @@
                                   "Camera specified on command line", config->camera);
 
-            if (!pmConfigCameraSkycellVersion(config->site, cameraName)) {
+            if (!pmConfigCameraSkycellVersion(config->complete, cameraName)) {
                 psError(PS_ERR_UNKNOWN, false,
                         "Unable to generate skycell versions of specified camera %s.\n",
@@ -655,5 +667,5 @@
             }
 
-            if (!pmConfigCameraMosaickedVersions(config->site, cameraName)) {
+            if (!pmConfigCameraMosaickedVersions(config->complete, cameraName)) {
                 psError(PS_ERR_UNKNOWN, false,
                         "Unable to generate mosaicked versions of specified camera %s.\n",
@@ -668,12 +680,12 @@
     if (!config->camera && readCameraConfig) {
         bool mdok;                      // Status of MD lookup
-        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS"); // List of cameras
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS"); // List of cameras
         if (!mdok || !cameras) {
-            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+            psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
             return false;
         }
 
         if (!metadataReadFiles(cameras, "camera configuration")) {
-            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within site configuration.\n");
+            psError(PS_ERR_UNKNOWN, false, "Unable to read cameras within system configuration.\n");
             psFree(config);
             return NULL;
@@ -702,10 +714,10 @@
         psFree(iter);
 
-        if (!pmConfigCameraSkycellVersionsAll(config->site)) {
+        if (!pmConfigCameraSkycellVersionsAll(config->complete)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to generate skycell versions of cameras.\n");
             psFree(config);
             return NULL;
         }
-        if (!pmConfigCameraMosaickedVersionsAll(config->site)) {
+        if (!pmConfigCameraMosaickedVersionsAll(config->complete)) {
             psError(PS_ERR_UNKNOWN, false, "Unable to generate mosaicked versions of cameras.\n");
             psFree(config);
@@ -715,5 +727,5 @@
 
     // Load the recipes from the camera file, if appropriate
-    if(!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_SITE | PM_RECIPE_SOURCE_CAMERA)) {
+    if(!pmConfigReadRecipes(config, PM_RECIPE_SOURCE_SYSTEM | PM_RECIPE_SOURCE_CAMERA)) {
         psError(PS_ERR_IO, false, "Failed to read recipes from camera file");
         psFree(config);
@@ -746,5 +758,5 @@
         psArgumentRemove(argNum, argc, argv);
 
-        psMetadata *cameras = psMetadataLookupMetadata(NULL, config->site, "CAMERAS"); // List of cameras
+        psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS"); // List of cameras
         if (!cameras) {
             psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find CAMERAS in the site configuration.\n");
@@ -794,5 +806,5 @@
         } else {
             char *dbserver = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->site, PS_LIST_TAIL, "DBSERVER", PS_META_REPLACE, NULL, dbserver)) {
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBSERVER", PS_META_REPLACE, NULL, dbserver)) {
                 psWarning("Failed to overwrite .ipprc DBSERVER value");
             }
@@ -809,5 +821,5 @@
         } else {
             char *dbname = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->site, PS_LIST_TAIL, "DBNAME", PS_META_REPLACE, NULL, dbname)) {
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBNAME", PS_META_REPLACE, NULL, dbname)) {
                 psWarning("Failed to overwrite .ipprc DBNAME value");
             }
@@ -824,5 +836,5 @@
         } else {
             char *dbuser = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->site, PS_LIST_TAIL, "DBUSER", PS_META_REPLACE, NULL, dbuser)) {
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBUSER", PS_META_REPLACE, NULL, dbuser)) {
                 psWarning("Failed to overwrite .ipprc DBUSER value");
             }
@@ -839,5 +851,5 @@
         } else {
             char *dbpassword = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddStr(config->site, PS_LIST_TAIL, "DBPASSWORD", PS_META_REPLACE,
+            if (!psMetadataAddStr(config->complete, PS_LIST_TAIL, "DBPASSWORD", PS_META_REPLACE,
                                   NULL, dbpassword)) {
                 psWarning("Failed to overwrite .ipprc DBPASSWORD value");
@@ -855,5 +867,5 @@
         } else {
             char *dbport = argv[argNum]; // The camera configuration file to read
-            if (!psMetadataAddS32(config->site, PS_LIST_TAIL, "DBPORT", PS_META_REPLACE, NULL,
+            if (!psMetadataAddS32(config->complete, PS_LIST_TAIL, "DBPORT", PS_META_REPLACE, NULL,
                                   (psS32)atoi(dbport))) {
                 psWarning("Failed to overwrite .ipprc DBPORT value");
@@ -1027,5 +1039,5 @@
     if (! config->camera) {
         bool mdok;                      // Metadata lookup status
-        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->site, "CAMERAS");
+        psMetadata *cameras = psMetadataLookupMetadata(&mdok, config->complete, "CAMERAS");
         if (! mdok || !cameras) {
             psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
@@ -1114,5 +1126,5 @@
     PS_ASSERT_STRING_NON_EMPTY(cameraName, NULL);
 
-    psMetadata *cameras = psMetadataLookupMetadata(NULL, config->site, "CAMERAS");
+    psMetadata *cameras = psMetadataLookupMetadata(NULL, config->complete, "CAMERAS");
     if (!cameras) {
         psError(PS_ERR_IO, true, "Unable to find CAMERAS in the configuration.");
@@ -1140,5 +1152,5 @@
 {
     PS_ASSERT_PTR_NON_NULL(config, NULL);
-    PS_ASSERT_PTR_NON_NULL(config->site, NULL);
+    PS_ASSERT_PTR_NON_NULL(config->complete, NULL);
 
     #ifndef HAVE_PSDB
@@ -1157,9 +1169,9 @@
 
     // XXX leaky strings
-    psString dbServer = psMetadataLookupStr(&mdStatus01, config->site, "DBSERVER");
-    psString dbUsername = psMetadataLookupStr(&mdStatus02, config->site, "DBUSER");
-    psString dbPassword = psMetadataLookupStr(&mdStatus03, config->site, "DBPASSWORD");
-    psString dbName = psMetadataLookupStr(&mdStatus04, config->site, "DBNAME");
-    psS32 dbPort = psMetadataLookupS32(&mdStatus05, config->site, "DBPORT");
+    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");
     if (!mdStatus05) {
         dbPort = 0;
@@ -1352,11 +1364,11 @@
     // replace path://PATH with matched datapath
     if (!strncasecmp(filename, "path://", strlen("path://"))) {
-        PS_ASSERT_METADATA_NON_NULL(config->site, NULL);
+        PS_ASSERT_METADATA_NON_NULL(config->complete, NULL);
 
         psString newName = psStringCopy(filename);
 
         // filename should be of the form: path://PATH/rest/of/file
-        // replace PATH with matching name from config->site:DATAPATH
-        psMetadata *datapath = psMetadataLookupPtr (NULL, config->site, "DATAPATH");
+        // replace PATH with matching name from config->complete:DATAPATH
+        psMetadata *datapath = psMetadataLookupPtr (NULL, config->complete, "DATAPATH");
         if (datapath == NULL) {
             psError(PS_ERR_UNKNOWN, true, "DATAPATH is not defined in config.site");
@@ -1410,5 +1422,5 @@
         // if env isn't set, check the config system
         if (!neb_server) {
-            neb_server = psMetadataLookupStr(&status, config->site, "NEB_SERVER");
+            neb_server = psMetadataLookupStr(&status, config->complete, "NEB_SERVER");
             if (!status) {
                 psError(PM_ERR_CONFIG, true, "failed to lookup config value for NEB_SERVER.");
Index: trunk/psModules/src/config/pmConfig.h
===================================================================
--- trunk/psModules/src/config/pmConfig.h	(revision 16608)
+++ trunk/psModules/src/config/pmConfig.h	(revision 16611)
@@ -5,6 +5,6 @@
  *  @author Eugene Magnier, IfA
  *
- *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2007-10-26 02:41:15 $
+ *  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-02-22 20:20:38 $
  *  Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -25,5 +25,5 @@
 typedef enum {
     PM_RECIPE_SOURCE_NONE        = 0x00, ///< None yet
-    PM_RECIPE_SOURCE_SITE        = 0x01, ///< Site configuration
+    PM_RECIPE_SOURCE_SYSTEM      = 0x01, ///< System configuration
     PM_RECIPE_SOURCE_CAMERA      = 0x02, ///< Camera configuration
     PM_RECIPE_SOURCE_CL          = 0x04, ///< Command-line
@@ -34,8 +34,11 @@
 /// Configuration information
 ///
-/// This structure stores the configuration information: the site, camera and recipe configuration, the
+/// This structure stores the configuration information: user, site, system, camera and recipe configuration, the
 /// command-line arguments, the pmFPAfiles used, and the database handle.
 typedef struct {
-    psMetadata *site;                   ///< Site configuration
+    psMetadata *user;                 	///< User configuration
+    psMetadata *site;                 	///< Site configuration
+    psMetadata *system;               	///< System configuration
+    psMetadata *complete;               ///< Full merged configuration
     psMetadata *camera;                 ///< Camera specification
     psString cameraName;                ///< Camera name
@@ -68,10 +71,10 @@
 /// Read configuration information from the command line.
 ///
-/// pmConfigRead loads the site configuration (the file name is specified by "-site SITE_FILE" on the
-/// command-line, the PS_SITE environment variable, or it is $HOME/.ipprc).  The configuration search path is
+/// pmConfigRead loads the user configuration (the file name is specified by "-ipprc FILE" on the
+/// command-line, the IPPRC environment variable, or it is $HOME/.ipprc).  The configuration search path is
 /// set. The camera configuration is loaded if it is specified on the command line ("-camera
 /// CAMERA_FILE"). Recipes specified on the command line ("-recipe RECIPE_NAME RECIPE_SOURCE") are also
 /// loaded.  These command-line arguments are removed from from the command-line, to simplify parsing.  The
-/// psLib log, trace and time setups are also performed if specified in the site configuration.
+/// psLib log, trace and time setups are also performed if specified in the user configuration.
 pmConfig *pmConfigRead(int *argc,       ///< Number of command-line arguments
                        char **argv, ///< Array of command-line arguments
@@ -166,5 +169,5 @@
 /// Get the file rule of interest
 ///
-/// Look up the name of the set of file rules to use, get that set from the site configuration, and return the
+/// Look up the name of the set of file rules to use, get that set from the system configuration, and return the
 /// appropriate rule from the set.
 psMetadata *pmConfigFileRule(const pmConfig *config, ///< Configuration
Index: trunk/psModules/src/config/pmConfigCamera.c
===================================================================
--- trunk/psModules/src/config/pmConfigCamera.c	(revision 16608)
+++ trunk/psModules/src/config/pmConfigCamera.c	(revision 16611)
@@ -24,18 +24,18 @@
 
 // Generate the skycell version of a named camera configuration
-bool pmConfigCameraSkycellVersion(psMetadata *site, // The site configuration
+bool pmConfigCameraSkycellVersion(psMetadata *system, // The system configuration
                                   const char *name // Name of the un-mosaicked camera
                                   )
 {
-    PS_ASSERT_METADATA_NON_NULL(site, false);
+    PS_ASSERT_METADATA_NON_NULL(system, false);
     PS_ASSERT_STRING_NON_EMPTY(name, false);
 
     bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, site, "CAMERAS"); // List of cameras
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
     if (!mdok || !cameras) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
-        return false;
-    }
-    if (!pmConfigGenerateSkycellVersion(cameras, cameras, name, site)) {
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
+        return false;
+    }
+    if (!pmConfigGenerateSkycellVersion(cameras, cameras, name, system)) {
         psError(PS_ERR_UNKNOWN, true, "Failed to build skycell camera description for %s\n", name);
         return false;
@@ -45,12 +45,12 @@
 
 
-bool pmConfigCameraSkycellVersionsAll(psMetadata *site)
-{
-    PS_ASSERT_METADATA_NON_NULL(site, false);
+bool pmConfigCameraSkycellVersionsAll(psMetadata *system)
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
 
     bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, site, "CAMERAS"); // List of cameras
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
     if (!mdok || !cameras) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
         return false;
     }
@@ -61,5 +61,5 @@
     while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
         assert(camerasItem->type == PS_DATA_METADATA); // Only metadata are allowed here!
-        if (!pmConfigGenerateSkycellVersion(cameras, new, camerasItem->name, site)) {
+        if (!pmConfigGenerateSkycellVersion(cameras, new, camerasItem->name, system)) {
             psError(PS_ERR_UNKNOWN, true, "Failed to build skycell camera description for %s\n",
                     camerasItem->name);
@@ -92,5 +92,5 @@
 static const char *skycellConceptName(const char *name, // Name of concept
                                       const char **concepts, // List of concepts NOT to update
-                                      const psMetadata *site // Site configuration
+                                      const psMetadata *system // System configuration
                                       )
 {
@@ -101,9 +101,9 @@
     }
 
-    if (!site) {
+    if (!system) {
         return name;
     }
     bool mdok;                          // Status of MD lookup
-    psMetadata *skycells = psMetadataLookupMetadata(&mdok, site, "SKYCELLS"); // Skycell concept headers
+    psMetadata *skycells = psMetadataLookupMetadata(&mdok, system, "SKYCELLS"); // Skycell concept headers
     if (!skycells) {
         return name;
@@ -121,5 +121,5 @@
                                     psMetadata *newCameras, // New list of camera configurations
                                     const char *name, // Name of original camera configuration
-                                    const psMetadata *site // Site configuration
+                                    const psMetadata *system // System configuration
                                     )
 {
@@ -213,5 +213,5 @@
         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
         while ((name = psListGetAndIncrement(iter))) {
-            const char *new = skycellConceptName(name, skycellConceptsFPA, site); // Name for skycell
+            const char *new = skycellConceptName(name, skycellConceptsFPA, system); // Name for skycell
             if (new) {
                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
@@ -224,5 +224,5 @@
         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
         while ((name = psListGetAndIncrement(iter))) {
-            const char *new = skycellConceptName(name, skycellConceptsChip, site); // Name for skycell
+            const char *new = skycellConceptName(name, skycellConceptsChip, system); // Name for skycell
             if (new) {
                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
@@ -235,5 +235,5 @@
         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
         while ((name = psListGetAndIncrement(iter))) {
-            const char *new = skycellConceptName(name, skycellConceptsCell, site); // Name for skycell
+            const char *new = skycellConceptName(name, skycellConceptsCell, system); // Name for skycell
             if (new) {
                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
@@ -299,15 +299,15 @@
 
 // Generate the Chip and FPA mosaicked version of a named camera configuration
-bool pmConfigCameraMosaickedVersions(psMetadata *site, // The site configuration
+bool pmConfigCameraMosaickedVersions(psMetadata *system, // The system configuration
                                      const char *name // Name of the un-mosaicked camera
                                     )
 {
-    PS_ASSERT_METADATA_NON_NULL(site, false);
+    PS_ASSERT_METADATA_NON_NULL(system, false);
     PS_ASSERT_STRING_NON_EMPTY(name, false);
 
     bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, site, "CAMERAS"); // List of cameras
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
     if (!mdok || !cameras) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
         return false;
     }
@@ -325,12 +325,12 @@
 // the operation putting the new entries first is now implemented in pmConfigGenerateMosaickedVersion
 // Generate the Chip and FPA mosaicked version of a named camera configuration
-bool pmConfigCameraMosaickedVersionsAll(psMetadata *site)
-{
-    PS_ASSERT_METADATA_NON_NULL(site, false);
+bool pmConfigCameraMosaickedVersionsAll(psMetadata *system)
+{
+    PS_ASSERT_METADATA_NON_NULL(system, false);
 
     bool mdok;                          // Status of MD lookup
-    psMetadata *cameras = psMetadataLookupMetadata(&mdok, site, "CAMERAS"); // List of cameras
+    psMetadata *cameras = psMetadataLookupMetadata(&mdok, system, "CAMERAS"); // List of cameras
     if (!mdok || !cameras) {
-        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the site configuration.\n");
+        psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find CAMERAS in the system configuration.\n");
         return false;
     }
Index: trunk/psModules/src/config/pmConfigCommand.c
===================================================================
--- trunk/psModules/src/config/pmConfigCommand.c	(revision 16608)
+++ trunk/psModules/src/config/pmConfigCommand.c	(revision 16611)
@@ -12,25 +12,27 @@
 {
     PS_ASSERT_PTR_NON_NULL(command, false);
+    PS_ASSERT_PTR_NON_NULL(config, false);
+    PS_ASSERT_PTR_NON_NULL(config->complete, false);
 
     bool mdok;                          // Status of MD lookup
-    const char *dbserver = psMetadataLookupStr(&mdok, config->site, "DBSERVER"); // Database server
+    const char *dbserver = psMetadataLookupStr(&mdok, config->complete, "DBSERVER"); // Database server
     if (!mdok || strlen(dbserver) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBSERVER in site configuration.\n");
-        return NULL;
+        return false;
     }
-    const char *dbname = psMetadataLookupStr(&mdok, config->site, "DBNAME"); // Database name
+    const char *dbname = psMetadataLookupStr(&mdok, config->complete, "DBNAME"); // Database name
     if (!mdok || strlen(dbname) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBNAME in site configuration.\n");
-        return NULL;
+        return false;
     }
-    const char *dbuser = psMetadataLookupStr(&mdok, config->site, "DBUSER"); // Database user
+    const char *dbuser = psMetadataLookupStr(&mdok, config->complete, "DBUSER"); // Database user
     if (!mdok || strlen(dbuser) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBUSER in site configuration.\n");
-        return NULL;
+        return false;
     }
-    const char *dbpassword = psMetadataLookupStr(&mdok, config->site, "DBPASSWORD"); // Database password
+    const char *dbpassword = psMetadataLookupStr(&mdok, config->complete, "DBPASSWORD"); // Database password
     if (!mdok || strlen(dbpassword) == 0) {
         psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find DBPASSWORD in site configuration.\n");
-        return NULL;
+        return false;
     }
 
Index: trunk/psModules/src/config/pmConfigRecipes.c
===================================================================
--- trunk/psModules/src/config/pmConfigRecipes.c	(revision 16608)
+++ trunk/psModules/src/config/pmConfigRecipes.c	(revision 16611)
@@ -11,5 +11,5 @@
 #include "pmConfigRecipes.h"
 
-static bool loadRecipeSite(bool *status, pmConfig *config, psMetadata *source);
+static bool loadRecipeSystem(bool *status, pmConfig *config, psMetadata *source);
 static bool loadRecipeCamera(bool *status, pmConfig *config, psMetadata *source);
 static bool loadRecipeFromArguments(bool *status, pmConfig *config);
@@ -46,7 +46,7 @@
 
 // this function may be called several times.  it attempts to load the recipe data from one of
-// three locations: config->site, config->camera, and argv.  We cannot read the recipes
+// three locations: config->complete, 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 site recipes.
+// camera and system recipes.
 bool pmConfigReadRecipes(pmConfig *config, pmRecipeSource source)
 {
@@ -58,13 +58,13 @@
     }
 
-    // Read the recipe file names from the site configuration and camera configuration
-    // It is an error for config->site:recipes not to exist.  all programs install their
-    // master recipe files in the site:recipe location when they are built.
-    if (config->site && (source & PM_RECIPE_SOURCE_SITE)) {
-        if (!loadRecipeSite(&status, config, config->site)) {
-            psError(PS_ERR_IO, false, "Failed to read recipes from site config");
-            return false;
-        }
-        psTrace ("psModules.config", 3, "read recipes from site config");
+    // 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
+    // master recipe files in the system:recipe location when they are built.
+    if (config->complete && (source & PM_RECIPE_SOURCE_SYSTEM)) {
+        if (!loadRecipeSystem(&status, config, config->complete)) {
+            psError(PS_ERR_IO, false, "Failed to read recipes from system config");
+            return false;
+        }
+        psTrace ("psModules.config", 3, "read recipes from system config");
     }
 
@@ -283,6 +283,6 @@
 }
 
-// Load the recipe files for SITE : REQUIRED
-static bool loadRecipeSite(bool *status,
+// Load the recipe files for SYSTEM : REQUIRED
+static bool loadRecipeSystem(bool *status,
                            pmConfig *config, // The configuration into which to read the recipes
                            psMetadata *source // The source configuration, from which to read the filenames
@@ -294,6 +294,6 @@
 
     if (!source) {
-        psError(PS_ERR_IO, true, "The site configuration has not been read --- cannot read recipes from this location.\n");
-        config->recipesRead &= ~PM_RECIPE_SOURCE_SITE;
+        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;
     }
@@ -301,5 +301,5 @@
     psMetadata *recipes = psMetadataLookupMetadata(NULL, source, "RECIPES"); // The list of recipes
     if (!recipes) {
-        psError(PS_ERR_IO, false, "RECIPES not found in the site configuration\n");
+        psError(PS_ERR_IO, false, "RECIPES not found in the system configuration\n");
         return false;
     }
@@ -313,5 +313,5 @@
         // type mismatch is a serious error
         if (fileItem->type != PS_DATA_STRING) {
-            psError(PS_ERR_IO, true, "%s in site configuration RECIPES is not of type STR", fileItem->name);
+            psError(PS_ERR_IO, true, "%s in system configuration RECIPES is not of type STR", fileItem->name);
             return false;
         }
@@ -320,5 +320,5 @@
         psMetadata *recipe = NULL;
         if (!pmConfigFileRead(&recipe, fileItem->data.str, "recipe")) {
-            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in site configuration\n",
+            psError(PS_ERR_IO, false, "Failed to read recipe file %s listed in system configuration\n",
                     fileItem->data.str);
             return false;
@@ -331,5 +331,5 @@
     }
     psFree(recipesIter);
-    config->recipesRead |= PM_RECIPE_SOURCE_SITE;
+    config->recipesRead |= PM_RECIPE_SOURCE_SYSTEM;
 
     *status = true;
@@ -337,7 +337,7 @@
 }
 
-// Load the recipe files (valid for SITE | CAMERA)
+// Load the recipe files (valid for SYSTEM | CAMERA)
 // each time we load a specific recipe, it overrides the existing metadata for that recipe
-// for sourceType == SITE | CAMERA, RECIPES contains a list of files to be read (pmConfigFileRead)
+// for sourceType == SYSTEM | CAMERA, RECIPES contains a list of files to be read (pmConfigFileRead)
 static bool loadRecipeCamera(bool *status, // status variable
                              pmConfig *config, // The configuration into which to read the recipes
Index: trunk/psModules/src/detrend/pmDetrendDB.c
===================================================================
--- trunk/psModules/src/detrend/pmDetrendDB.c	(revision 16608)
+++ trunk/psModules/src/detrend/pmDetrendDB.c	(revision 16611)
@@ -115,5 +115,4 @@
     PS_ASSERT_PTR_NON_NULL(options, NULL);
     PS_ASSERT_PTR_NON_NULL(config, NULL);
-    PS_ASSERT_PTR_NON_NULL(config->site, NULL);
 
     int status, exit_status;
@@ -150,7 +149,15 @@
         psStringAppend(&line, " -airmass %f", options->twilight);
     }
-
-    pmConfigDatabaseCommand(&line, config);
-    pmConfigTraceCommand(&line);
+    
+    if (!pmConfigDatabaseCommand(&line, config)) {
+        psError (PS_ERR_IO, false, "error building detrend command %s", line);
+        goto failure;
+    }
+
+    if (!pmConfigTraceCommand(&line)) {
+        psError (PS_ERR_IO, false, "error building detrend command %s", line);
+        goto failure;
+    }
+
     psTrace("psModules.detrend", 5, "running %s", line);
 
