Index: /trunk/ippTools/src/Makefile.am
===================================================================
--- /trunk/ippTools/src/Makefile.am	(revision 7970)
+++ /trunk/ippTools/src/Makefile.am	(revision 7971)
@@ -7,5 +7,6 @@
 	dettool \
 	pzgetexp \
-	pzgetimfiles
+	pzgetimfiles \
+	pxinject
 
 include_HEADERS = pxtools.h
@@ -19,5 +20,6 @@
 	p1search.h \
 	p2search.h \
-	dettool.h
+	dettool.h \
+	pxinject.h
 
 lib_LTLIBRARIES = libpxtools.la
@@ -88,4 +90,10 @@
     dettoolConfig.c
 
+pxinject_CFLAGS = $(PSLIB_CFLAGS) $(PSMODULES_CFLAGS) $(IPPDB_CFLAGS) $(pxtools_CFLAGS)
+pxinject_LDADD = $(PSLIB_LIBS) $(PSMODULES_LIBS) $(IPPDB_LIBS) $(top_builddir)/src/libpxtools.la
+pxinject_SOURCES = \
+    pxinject.c \
+    pxinjectConfig.c
+
 clean-local:
 	-rm -f TAGS
Index: /trunk/ippTools/src/pxinject.c
===================================================================
--- /trunk/ippTools/src/pxinject.c	(revision 7971)
+++ /trunk/ippTools/src/pxinject.c	(revision 7971)
@@ -0,0 +1,56 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <ippdb.h>
+
+#include "pxtools.h"
+#include "pxinject.h"
+
+static bool newExpMode(pxConfig *config);
+static bool newImfileMode(pxConfig *config);
+
+# define MODECASE(caseName, func) \
+    case caseName: \
+    if (!func(config)) { \
+        goto FAIL; \
+    } \
+    break;
+
+int main(int argc, char **argv)
+{
+    psLibInit(NULL);
+
+    pxConfig *config = pxinjectConfig(NULL, argc, argv);
+
+    switch (config->mode) {
+        MODECASE(PXINJECT_MODE_NEWEXP, newExpMode);
+        MODECASE(PXINJECT_MODE_NEWIMFILE, newImfileMode);
+        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);
+}
+
+static bool newExpMode(pxConfig *config)
+{
+    return true;
+}
+
+static bool newImfileMode(pxConfig *config)
+{
+    return true;
+}
Index: /trunk/ippTools/src/pxinject.h
===================================================================
--- /trunk/ippTools/src/pxinject.h	(revision 7971)
+++ /trunk/ippTools/src/pxinject.h	(revision 7971)
@@ -0,0 +1,14 @@
+#ifndef PXINJECT_H
+#define PXINJECT_H 1
+
+#include "pxtools.h"
+
+typedef enum {
+    PXINJECT_MODE_NONE           = 0x0,
+    PXINJECT_MODE_NEWEXP,
+    PXINJECT_MODE_NEWIMFILE
+} pxinjectMode;
+
+pxConfig *pxinjectConfig(pxConfig *config, int argc, char **argv);
+
+#endif // PXINJECT_H
Index: /trunk/ippTools/src/pxinjectConfig.c
===================================================================
--- /trunk/ippTools/src/pxinjectConfig.c	(revision 7971)
+++ /trunk/ippTools/src/pxinjectConfig.c	(revision 7971)
@@ -0,0 +1,175 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pmConfig.h>
+
+#include "pxtools.h"
+#include "pxinject.h"
+
+// this function can not fail -- exits on error
+pxConfig *pxinjectConfig(pxConfig *config, int argc, char **argv) {
+    if (!config) {
+        config = pxConfigAlloc();
+    }
+
+    // setup site config
+    config->modules = pmConfigRead(&argc, argv);
+    if (!config->modules) {
+        psError(PS_ERR_UNKNOWN, false, "Can't find site configuration");
+        goto FAIL;
+    }
+
+    // -newExp
+    psMetadata *newExpArgs = psMetadataAlloc();
+
+    // -newImfile
+    psMetadata *newImfileArgs = psMetadataAlloc();
+
+#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); \
+    } \
+}
+
+    // find which mode we're running under
+    PXTOOL_MODE("-newExp",          PXINJECT_MODE_NEWEXP,       newExpArgs);
+    PXTOOL_MODE("-newImfile",       PXINJECT_MODE_NEWIMFILE,    newImfileArgs);
+
+    bool argErr = false;
+    if (config->mode == PXINJECT_MODE_NONE) {
+        argErr = true;
+        fprintf (stderr, "mode argument is required\n");
+    } else if (! psArgumentParse(config->args, &argc, argv) || argc != 1) {
+        argErr = true;
+        fprintf (stderr, "error parsing arguments\n");
+    }
+
+    if (argErr) {
+        printf("\nPan-STARRS Detrend Tool\n");
+        printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
+        printf(" <mode> : [-newExp|-newImfile]\n\n");
+        fprintf (stdout, "-newExp ");
+        psArgumentHelp(newExpArgs);
+        psFree(newExpArgs);
+        fprintf (stdout, "-newImfile ");
+        psArgumentHelp(newImfileArgs);
+        psFree(newImfileArgs);
+
+        goto FAIL;
+    }
+
+    psFree(newExpArgs);
+    psFree(newImfileArgs);
+
+    // 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(det_id);
+    {
+        int n = 0;
+        bool status = false;
+        if ((n = psMetadataLookupS32(&status, config->args, "-iteration"))) {
+            if (!psMetadataAddS32(config->where, PS_LIST_TAIL, "iteration", 0, "==", n)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+                goto FAIL;
+            }
+        }
+    }
+    addWhereStr(det_type);
+    addWhereStr(exp_id);
+    addWhereStr(class_id);
+    // convert '-inst' to 'camera'
+    {
+        psString str = NULL;
+        bool status = false;
+        if ((str = psMetadataLookupStr(&status, config->args, "-inst"))) {
+            if (!psMetadataAddStr(config->where, PS_LIST_TAIL, "camera", 0, "==", str)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+                goto FAIL;
+            }
+        }
+    }
+    addWhereStr(telescope);
+    addWhereStr(exp_type);
+    {
+        int n = 0;
+        bool status = false;
+        if ((n = psMetadataLookupS32(&status, config->args, "-imfiles"))) {
+            if (!psMetadataAddS32(config->where, PS_LIST_TAIL, "imfiles", 0, "==", n)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+                goto FAIL;
+            }
+        }
+    }
+    addWhereStr(filter);
+    addWhereStr(stats);
+    addWhereStr(recipe);
+    {
+        int n = 0;
+        bool status = false;
+        if ((n = psMetadataLookupS32(&status, config->args, "-p1_version"))) {
+            if (!psMetadataAddS32(config->where, PS_LIST_TAIL, "p1_version", 0, "==", n)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+                goto FAIL;
+            }
+        }
+    }
+    {
+        bool boolean = false;
+        bool status = false;
+
+        if ((boolean = psMetadataLookupBool(&status, config->args, "-accept"))) {
+            if (!psMetadataAddBool(config->where, PS_LIST_TAIL, "accept", 0, "==", boolean)) {
+                psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+                goto FAIL;
+            }
+        }
+    }
+
+    if (config->where->list->n < 1) {
+        psFree(config->where);
+        config->where = NULL;
+    }
+
+    // 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");
+        goto FAIL;
+    }
+
+    // save argv/argc
+    config->argv = argv;
+    config->argc = argc;
+
+    return config;
+
+FAIL:
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+    exit(EXIT_FAILURE);
+}
