Index: /trunk/ippTools/src/pztool.c
===================================================================
--- /trunk/ippTools/src/pztool.c	(revision 7920)
+++ /trunk/ippTools/src/pztool.c	(revision 7921)
@@ -16,32 +16,38 @@
 static bool pzsearchFlushPendingExp(pxConfig *config);
 
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+                goto FAIL; \
+            } \
+    break;
+
+
 int main(int argc, char **argv)
 {
+    psLibInit(NULL);
+
     pxConfig *config = pzsearchConfig(NULL, argc, argv);
 
     switch (config->mode) {
-        case PX_MODE_SEEN:
-            if (!seenMode(config)) {
-                goto FAIL;
-            }
-            break;
-        case PX_MODE_PENDING:
-            if (!pendingMode(config)) {
-                goto FAIL;
-            }
-            break;
-        case PX_MODE_COPYDONE:
-            if (!copydoneMode(config)) {
-                goto FAIL;
-            }
-            break;
+        MODECASE(PZSEARCH_MODE_SEEN, seenMode);
+        MODECASE(PZSEARCH_MODE_PENDING, pendingMode);
+        MODECASE(PZSEARCH_MODE_COPYDONE, copydoneMode);
         default:
             psAbort(argv[0], "invalid option (this should not happen)");
     }
 
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
+
     exit(EXIT_SUCCESS);
 
 FAIL:
     psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+
     exit(EXIT_FAILURE);
 }
Index: /trunk/ippTools/src/pztool.h
===================================================================
--- /trunk/ippTools/src/pztool.h	(revision 7920)
+++ /trunk/ippTools/src/pztool.h	(revision 7921)
@@ -4,4 +4,11 @@
 #include "pxtools.h"
 
+typedef enum {
+    PZSEARCH_MODE_NONE      = 0x0,
+    PZSEARCH_MODE_SEEN,
+    PZSEARCH_MODE_PENDING,
+    PZSEARCH_MODE_COPYDONE
+} pzsearchMode;
+
 pxConfig *pzsearchConfig(pxConfig *config, int argc, char **argv);
 
Index: /trunk/ippTools/src/pztoolConfig.c
===================================================================
--- /trunk/ippTools/src/pztoolConfig.c	(revision 7920)
+++ /trunk/ippTools/src/pztoolConfig.c	(revision 7921)
@@ -6,5 +6,7 @@
 
 #include "pxtools.h"
+#include "pzsearch.h"
 
+// this function can not fail -- exits on error
 pxConfig *pzsearchConfig(pxConfig *config, int argc, char **argv) {
     if (!config) {
@@ -12,6 +14,6 @@
     }
 
+    // setup site config
     config->modules = pmConfigRead(&argc, argv);
-
     if (! config->modules) {
         psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
@@ -19,54 +21,59 @@
     }
 
-    int N;
-    config->mode = PX_MODE_NONE;
-    if ((N = psArgumentGet (argc, argv, "-seen"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_SEEN;
-    }
-    if ((N = psArgumentGet (argc, argv, "-pending"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_PENDING;
-    }
-    if ((N = psArgumentGet (argc, argv, "-copydone"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_COPYDONE;
-    }
+    // -seen
+    psMetadata *seenArgs = psMetadataAlloc();
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_id",  0,
+        "define exposure ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-inst",  0,
+        "define camera ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-telescope",  0,
+        "define telescope ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_type",  0,
+        "define exposure type", NULL); 
+    
+    // -pending
+    psMetadata *pendingArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-exp_id",  0,
+        "define exposure ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-inst",  0,
+        "define camera ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-telescope",  0,
+        "define telescope ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-exp_type",  0,
+        "define exposure type", NULL); 
 
-    // paul's argument parsing convention requires: -key value
-    // Parse other command-line arguments
-    psMetadata *args = psMetadataAlloc();
-    psMetadataAddStr(args , PS_LIST_TAIL, "-seen", 0,
-        "list all uncopied exposure IDs", "");
-    psMetadataAddStr(args , PS_LIST_TAIL, "-pending",  0,
-        "list all image files pending download", "");
-    psMetadataAddStr(args , PS_LIST_TAIL, "-copydone",  0,
-        "indicate that an image file has been downloaded", "");
-
-    // -copydone search
+    // -copydone
     psMetadata *copydoneArgs = psMetadataAlloc();
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-exp_id",  0,
-        "define exposure ID", "");
+        "define exposure ID", NULL); 
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class",  0,
-        "define class", "");
+        "define class", NULL);
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class_id",  0,
-        "define class_id", "");
+        "define class_id", NULL);
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-suri",  0,
-        "define storage uri", "");
+        "define storage uri", NULL);
+
+#define PXTOOL_MODE(option, modeval, argset) \
+{ \
+    int N = 0; \
+    if ((N = psArgumentGet (argc, argv, option))) { \
+        psArgumentRemove (N, &argc, argv); \
+        if (config->mode) { \
+            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed"); \
+        } \
+        config->mode = modeval; \
+        config->args = psMemIncrRefCounter(argset); \
+    } \
+}
+
+    PXTOOL_MODE("-seen",            PZSEARCH_MODE_SEEN,         seenArgs);
+    PXTOOL_MODE("-pending",         PZSEARCH_MODE_PENDING,      pendingArgs);
+    PXTOOL_MODE("-copydone",        PZSEARCH_MODE_COPYDONE,     copydoneArgs);
 
     bool argErr = false;
-    if (config->mode == PX_MODE_NONE) {
+    if (config->mode == PZSEARCH_MODE_NONE) {
         argErr = true;
         fprintf (stderr, "mode argument is required\n");
-    } else if (! psArgumentParse(args, &argc, argv) || argc != 1) {
+    } else if (! psArgumentParse(config->args, &argc, argv) || argc != 1) {
         argErr = true;
         fprintf (stderr, "error parsing arguments\n");
@@ -77,62 +84,68 @@
         printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
         printf(" <mode> : -seen | -pending | -copydone\n\n");
+
+        fprintf (stdout, "-seen ");
+        psArgumentHelp(seenArgs);
+        psFree(seenArgs);
+
+        fprintf (stdout, "-pending ");
+        psArgumentHelp(pendingArgs);
+        psFree(pendingArgs);
+
         fprintf (stdout, "-copydone ");
         psArgumentHelp(copydoneArgs);
-        psFree(args);
         psFree(copydoneArgs);
-        exit(EXIT_FAILURE);
+
+        goto FAIL;
     }
 
+    psFree(seenArgs);
+    psArgumentHelp(pendingArgs);
     psFree(copydoneArgs);
 
-    // XXX why is "" being returned when -[foo] isn't specified?
-#define EMPTY_TO_NULL_STRING(var) \
-    if (var != NULL && strcmp(var, "") == 0) { \
-        var = NULL; \
+    // setup search criterion
+#define addWhereStr(name) \
+{ \
+    psString str = NULL; \
+    bool status = false; \
+    if ((str = psMetadataLookupStr(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddStr(config->where, PS_LIST_TAIL, #name, 0, "==", str)) {\
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            goto FAIL; \
+        } \
+    } \
+}
+
+    // generate SQL where claus
+    config->where = psMetadataAlloc();
+
+    addWhereStr(exp_id); 
+    addWhereStr(class); 
+    addWhereStr(class_id); 
+
+    if (config->where->list->n < 1) {
+        psFree(config->where);
+        config->where = NULL;
     }
 
-    config->args = args;
-
-if (config->mode == PX_MODE_COPYDONE) {
-    psMetadata *where = psMetadataAlloc();
-
-    bool status;
-    psString str;
-    if ((str = psMetadataLookupStr(&status, args, "-exp_id"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-    if ((str = psMetadataLookupStr(&status, args, "-class"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "class", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item class");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-    if ((str = psMetadataLookupStr(&status, args, "-class_id"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "class_id", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    if (where->list->n < 1) {
-        psFree(where);
-        where = NULL;
-    }
-    config->where = where;
-}
-
     // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
     config->dbh = pmConfigDB(config->modules);
     if (!config->dbh) {
         psError(PS_ERR_UNKNOWN, false, "Can't configure database");
-        exit(EXIT_FAILURE);
+        goto FAIL;
     }
 
+    // save argv/argc
+    config->argv = argv;
+    config->argc = argc;
+
     return config;
+
+FAIL:
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+    exit(EXIT_FAILURE);
 }
