Index: trunk/psModules/src/config/pmConfig.c
===================================================================
--- trunk/psModules/src/config/pmConfig.c	(revision 9992)
+++ trunk/psModules/src/config/pmConfig.c	(revision 10421)
@@ -4,6 +4,6 @@
  *  @author EAM (IfA)
  *
- *  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2006-11-15 02:34:18 $
+ *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2006-12-03 18:48:10 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -454,4 +454,5 @@
 
 
+// XXX aren't these (return false) below errors: call psError?
 bool pmConfigValidateCameraFormat(const psMetadata *cameraFormat, const psMetadata *header)
 {
@@ -463,5 +464,5 @@
     psMetadata *rule = psMetadataLookupMetadata(&mdStatus, cameraFormat, "RULE");
     if (! mdStatus || ! rule) {
-        psLogMsg(__func__, PS_LOG_WARN, "Unable to read rule for camera.\n");
+        psError(PS_ERR_UNKNOWN, true, "Unable to read rule for camera.\n");
         return false;
     }
@@ -472,9 +473,9 @@
     while ((ruleItem = psMetadataGetAndIncrement(ruleIter))) {
         // Check for the existence of the rule
-        psMetadataItem *headerItem = psMetadataLookup((psMetadata*)header, ruleItem->name);
+        psMetadataItem *headerItem = psMetadataLookup(header, ruleItem->name);
         if (! headerItem) {
             // It doesn't have a required header keyword, so it's not it
             psFree(ruleIter);
-            psTrace("psModules.config", 5, "Can't find %s\n", ruleItem->name);
+            psError(PS_ERR_UNKNOWN, true, "Can't find %s\n", ruleItem->name);
             return false;
         }
@@ -482,5 +483,5 @@
         // Check to see if the rule works
         if (! psMetadataItemCompare(headerItem, ruleItem)) {
-            psTrace("psModules.config", 5, "%s doesn't match.\n", ruleItem->name);
+            psError(PS_ERR_UNKNOWN, true, "%s doesn't match.\n", ruleItem->name);
             psFree(ruleIter);
             return false;
@@ -938,13 +939,14 @@
             glob (words->data[i], 0, NULL, &globList);
 
+            // if the glob does not match, save the literal word:
+            // otherwise save all glob matches
             if (globList.gl_pathc == 0) {
-                psError(PS_ERR_IO, true, "No match for %s", (char *)words->data[i]);
-                return input;
-            }
-
-            for (int j = 0; j < globList.gl_pathc; j++) {
-                char *filename = psStringCopy (globList.gl_pathv[j]);
-                psArrayAdd (input, 16, filename);
-                psFree (filename);
+                psArrayAdd (input, 16, words->data[i]);
+            } else {
+                for (int j = 0; j < globList.gl_pathc; j++) {
+                    char *filename = psStringCopy (globList.gl_pathv[j]);
+                    psArrayAdd (input, 16, filename);
+                    psFree (filename);
+                }
             }
         }
@@ -1008,2 +1010,61 @@
     return true;
 }
+
+// convert the supplied name, create a new output psString
+psString pmConfigConvertFilename (char *filename, pmConfig *config)
+{
+
+    psString newName = psStringCopy (filename);
+
+    // strip file:// from front of name
+    if (!strncasecmp (newName, "file://", strlen("file://"))) {
+        newName = psStringSubstitute (newName, "", "file://");
+    }
+
+    // replace path://PATH with matched datapath
+    if (!strncasecmp (newName, "path://", strlen("path://"))) {
+        // 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");
+        if (datapath == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "DATAPATH is not defined in config.site");
+            psFree (newName);
+            return NULL;
+        }
+
+        char *point = newName + strlen("path://");
+        char *mark = strchr (point, '/');
+        if (mark == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "syntax error in PATH-style name %s", newName);
+            psFree (newName);
+            return false;
+        }
+
+        psString path = psStringNCopy (point, mark - point);
+        char *realpath = psMetadataLookupStr (NULL, datapath, path);
+        if (realpath == NULL) {
+            psError(PS_ERR_UNKNOWN, true, "path (%s) not defined in config.site:DATAPATH for PATH-style name %s", path, newName);
+            psFree (newName);
+            psFree (path);
+            return false;
+        }
+        psFree (path);
+
+        char *tmpName = NULL;
+        psStringAppend (&tmpName, "%s/%s", realpath, mark + 1);
+        psFree (newName);
+        newName = tmpName;
+    }
+
+    // substitute neb://name with matched nebulous name
+
+    // if we still have a relative path, prepend WORKDIR:
+    if (newName[0] != '/') {
+        char *workdir = psMetadataLookupStr (NULL, config->site, "WORKDIR");
+        if (workdir) {
+            psStringPrepend (&newName, "%s/", workdir);
+        }
+    }
+
+    return newName;
+}
