Index: trunk/ppbgrestore/Makefile.am
===================================================================
--- trunk/ppbgrestore/Makefile.am	(revision 25972)
+++ trunk/ppbgrestore/Makefile.am	(revision 25972)
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES = *~ core core.*
Index: trunk/ppbgrestore/autogen.sh
===================================================================
--- trunk/ppbgrestore/autogen.sh	(revision 25972)
+++ trunk/ppbgrestore/autogen.sh	(revision 25972)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=ppbgrestore
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOLIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOLIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: trunk/ppbgrestore/configure.ac
===================================================================
--- trunk/ppbgrestore/configure.ac	(revision 25972)
+++ trunk/ppbgrestore/configure.ac	(revision 25972)
@@ -0,0 +1,46 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.61)
+
+AC_INIT([ppbgrestore], [0.1.1], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDCFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+dnl ------------------------------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+PKG_CHECK_MODULES([PSPHOT], [psphot >= 0.9.0])
+
+dnl Set CFLAGS for build
+IPP_STDOPTS
+CFLAGS="${CFLAGS} -Wall -Werror"
+# echo "PPSTAMP_CFLAGS: $PPSTAMP_CFLAGS"
+# echo "PPSTAMP_LIBS: $PPSTAMP_LIBS"
+
+AC_SUBST([PPSTAMP_CFLAGS])
+AC_SUBST([PPSTAMP_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+
+AC_OUTPUT
Index: trunk/ppbgrestore/src/Makefile.am
===================================================================
--- trunk/ppbgrestore/src/Makefile.am	(revision 25972)
+++ trunk/ppbgrestore/src/Makefile.am	(revision 25972)
@@ -0,0 +1,24 @@
+bin_PROGRAMS = ppbgrestore
+
+
+noinst_HEADERS = \
+	ppbgrestore.h
+
+ppbgrestore_CPPFLAGS = $(PSPHOT_CFLAGS)  $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+
+ppbgrestore_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 
+
+ppbgrestore_SOURCES = \
+	ppbgrestore.c \
+	ppbgrestoreArguments.c \
+	ppbgrestoreCleanup.c \
+	ppbgrestoreLoop.c \
+	ppbgrestoreParseCamera.c \
+	ppbgrestoreVersion.c
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
Index: trunk/ppbgrestore/src/ppbgrestore.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestore.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestore.c	(revision 25972)
@@ -0,0 +1,50 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ppbgrestore.h"
+
+#define TIMER_TOTAL "PPBGRESTORE_TOTAL"
+
+int main(int argc, char **argv) {
+
+    psLibInit(NULL);
+
+    psTimerStart(TIMER_TOTAL);
+
+    // Parse the configuration and arguments
+    // Open the input image(s)
+    // Determine camera, format from header if not already defined
+    // Construct camera in preparation for reading
+    pmConfig *config = ppbgrestoreArguments(argc, argv);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse command-line arguments.");
+        ppbgrestoreCleanup(config, NULL);
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    ppbgrestoreVersionPrint();
+
+    // define recipe options
+    // define the active I/O files
+    ppbgrestoreOptions *options = ppbgrestoreParseCamera(config);
+    if (options == NULL) {
+        psErrorStackPrint(stderr, "Unable to parse camera.");
+        ppbgrestoreCleanup(config, options);
+        exit(PS_EXIT_CONFIG_ERROR);
+    }
+
+    // Image Arithmetic Loop
+    if (!ppbgrestoreLoop(config, options)) {
+        psErrorStackPrint(stderr, "Unable to loop over input");
+        ppbgrestoreCleanup(config, options);
+        exit(PS_EXIT_SYS_ERROR);
+    }
+
+    psLogMsg("ppbgrestore", PS_LOG_INFO, "Complete ppbgrestore run: %f sec\n", psTimerMark(TIMER_TOTAL));
+
+    // Cleaning up
+    ppbgrestoreCleanup(config, options);
+
+    return PS_EXIT_SUCCESS;
+}
Index: trunk/ppbgrestore/src/ppbgrestore.h
===================================================================
--- trunk/ppbgrestore/src/ppbgrestore.h	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestore.h	(revision 25972)
@@ -0,0 +1,154 @@
+#ifndef PP_BG_RESTORE_H
+#define PP_BG_RESTORE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>  // for strcasecmp
+#include <unistd.h>   // for unlink
+#include "pslib.h"
+#include "psmodules.h"
+#include "psphot.h"
+#include "psastro.h"
+#include "ppStats.h"
+
+// Options for ppbgrestore processing
+typedef struct {
+    // actions which ppbgrestore should perform
+    bool dummy;
+#ifdef notdef
+    bool doMaskBuild;                   // Build internal mask
+    bool doVarianceBuild;               // Build internal variance map
+    bool doMaskBurntool;                // mask potential burntool trails
+    bool doMaskSat;                     // mask saturated pixels
+    bool doMaskLow;                     // mask low pixels
+    bool doMask;                        // Mask bad pixels
+    bool doNonLin;                      // Non-linearity correction
+    bool doOverscan;                    // Overscan subtraction
+    bool doNoiseMap;                    // Bias subtraction
+    bool doBias;                        // Bias subtraction
+    bool doDark;                        // Dark subtraction
+    bool doRemnance;                    // Remnance masking
+    bool doShutter;                     // Shutter correction
+    bool doFlat;                        // Flat-field normalisation
+    bool doPattern;                     // Pattern noise subtraction
+    bool doFringe;                      // Fringe subtraction
+    bool doPhotom;                      // Source identification and photometry
+    bool doBG;                          // Background subtraction
+    bool doAstromChip;                  // per-chip Astrometry
+    bool doAstromMosaic;                // full-mosaic Astrometry
+    bool doStats;                       // call ppStats on the image
+    bool checkCTE;                      // measure pixel-based variance
+    bool applyParity;                   // Apply Cell parities
+
+    bool doCrosstalkMeasure;            // measure crosstalk signal
+    bool doCrosstalkCorrect;            // apply crosstalk correction
+
+    // output files requested
+    bool BaseFITS;
+    bool BaseMaskFITS;
+    bool BaseVarianceFITS;
+
+    bool ChipFITS;
+    bool ChipMaskFITS;
+    bool ChipVarianceFITS;
+
+    bool FPA1FITS;
+    bool FPA2FITS;
+    bool Bin1FITS;
+    bool Bin1JPEG;
+    bool Bin2FITS;
+    bool Bin2JPEG;
+
+    // make values for abstract concepts of masking
+    psImageMaskType maskValue;          // apply this bit-mask to choose masked bits
+    psImageMaskType markValue;          // apply this bit-mask to choose masked bits
+    psImageMaskType satMask;            // Mask value to give saturated pixels
+    psImageMaskType lowMask;            // Mask value to give bad pixels
+    psImageMaskType flatMask;           // Mask value to give bad flat pixels
+    psImageMaskType darkMask;           // Mask value to give bad dark pixels
+    psImageMaskType blankMask;          // Mask value to give blank pixels
+    psImageMaskType burntoolMask;       // Suspect pixels that fall where a burntool trail is expected.
+    // non-linear correction parameters
+    psDataType nonLinearType;
+    psMetadataItem *nonLinearData;
+    void *nonLinearSource;
+
+    // options for the analysis
+    pmOverscanOptions *overscan;        // Overscan options
+    int burntoolTrails;
+    // binning parameters
+    int xBin1;                          // x-binning, scale 1
+    int yBin1;                          // y-binning, scale 1
+    int xBin2;                          // x-binning, scale 2
+    int yBin2;                          // y-binning, scale 2
+
+    // parameters used by the fringe analysis
+    float fringeRej;                    // Fringe rejection limit
+    int fringeIter;                     // Fringe iterations
+    float fringeKeep;                   // Fringe keep fraction
+
+    // Pattern noise subtraction
+    int patternOrder;                   // Polynomial order
+    int patternIter;                    // Clipping iterations
+    float patternRej;                   // Clipping threshold
+    float patternThresh;                // Ignore threshold
+    psStatsOptions patternMean;         // Statistic for mean
+    psStatsOptions patternStdev;        // Statistic for stdev
+
+    int remnanceSize;                   // Size for remnance detection
+    float remnanceThresh;               // Threshold for remnance detection
+
+    char *normClass;                    // class to use for per-class normalization
+#endif
+} ppbgrestoreOptions;
+
+
+ppbgrestoreOptions *ppbgrestoreOptionsAlloc(void);
+
+// Determine the processing options
+ppbgrestoreOptions *ppbgrestoreOptionsParse(pmConfig *config);
+
+// Get the configuration
+pmConfig *ppbgrestoreArguments(int argc, char **argv);
+
+// Determine what type of camera, and initialise
+ppbgrestoreOptions *ppbgrestoreParseCamera(pmConfig *config);
+
+// Loop over the input
+bool ppbgrestoreLoop(pmConfig *config, ppbgrestoreOptions *options);
+
+// free memory, check for leaks
+void ppbgrestoreCleanup (pmConfig *config, ppbgrestoreOptions *options);
+
+// Subtract background from the chip-mosaicked image
+bool ppbgrestoreRestoreBackground(
+    pmConfig *config,                   // Configuration
+    const pmFPAview *view,              // View to chip of interest
+    const ppbgrestoreOptions *options       // Processing options
+    );
+
+
+/// Return short version information
+psString ppbgrestoreVersion(void);
+
+/// Return software source
+psString ppbgrestoreSource(void);
+
+/// Return long version information
+psString ppbgrestoreVersionLong(void);
+
+/// Populate the header with version information for all dependencies
+bool ppbgrestoreVersionHeader(psMetadata *metadata ///< Header to populate
+    );
+
+/// Print version information
+void ppbgrestoreVersionPrint(void);
+
+
+void ppbgrestoreFileCheck(pmConfig *config);
+
+#endif
Index: trunk/ppbgrestore/src/ppbgrestoreArguments.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreArguments.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreArguments.c	(revision 25972)
@@ -0,0 +1,31 @@
+#include "ppbgrestore.h"
+
+void usage()
+{
+    fprintf(stderr, "USAGE: ppbgrestore [-file INPUT.fits] | [-list INPUT.txt] [-backmdl BACKMDL.fits] | [-backmdllist BACKMDL.txt] OUTPUT\n\n");
+    exit(2);
+}   
+pmConfig *ppbgrestoreArguments(int argc, char *argv[])
+{
+    pmConfig *config = pmConfigRead(&argc, argv, NULL);
+    if (config == NULL) {
+        psErrorStackPrint(stderr, "Can't find site configuration!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // the input file is a required argument if not found we will exit
+    if (!pmConfigFileSetsMD(config->arguments, &argc, argv, "INPUT", "-file", "-list")) {
+        fprintf(stderr, "input file is required\n");
+        usage();
+    }
+    if (!pmConfigFileSetsMD(config->arguments, &argc, argv, "BACKMDL", "-backmdl", "-backmdllist")) {
+        fprintf(stderr, "backmdl file is required\n");
+        usage();
+    }
+    if (argc != 2) usage ();
+
+    // Add the input and output images (which remain on the command-line) to the arguments list
+    psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "Name of the output image", argv[1]);
+
+    return config;
+}
Index: trunk/ppbgrestore/src/ppbgrestoreCleanup.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreCleanup.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreCleanup.c	(revision 25972)
@@ -0,0 +1,6 @@
+#include "ppbgrestore.h"
+
+void ppbgrestoreCleanup(pmConfig *config, ppbgrestoreOptions *options)
+{
+    // XXX: todo
+}
Index: trunk/ppbgrestore/src/ppbgrestoreLoop.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreLoop.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreLoop.c	(revision 25972)
@@ -0,0 +1,160 @@
+#include "ppbgrestore.h"
+#include "psphot.h"
+
+#define ESCAPE(MESSAGE) { \
+  psError(PS_ERR_UNKNOWN, false, MESSAGE); \
+  psFree(view); \
+  return false; \
+}
+
+
+bool ppbgrestoreLoop(pmConfig *config, ppbgrestoreOptions *options)
+{
+    bool status;                        // Status of MD lookup
+    pmFPAfile *input = psMetadataLookupPtr(&status, config->files, "PPBGRESTORE.INPUT");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find input data!\n");
+        ppbgrestoreCleanup(config, options);
+        exit(PS_EXIT_PROG_ERROR);
+    }
+    pmFPAfile *backmdl = psMetadataLookupPtr(&status, config->files, "PPBGRESTORE.BACKMDL");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find background model data!\n");
+        ppbgrestoreCleanup(config, options);
+        exit(PS_EXIT_PROG_ERROR);
+    }
+    pmFPAfile *output= psMetadataLookupPtr(&status, config->files, "PPBGRESTORE.OUTPUT");
+    if (!status) {
+        psErrorStackPrint(stderr, "Can't find output data!\n");
+        ppbgrestoreCleanup(config, options);
+        exit(PS_EXIT_PROG_ERROR);
+    }
+
+    pmFPAview *view = pmFPAviewAlloc(0);// View for level of interest
+//    pmHDU *lastHDU = NULL;              // Last HDU that was updated
+
+    // files associated with the science image
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+        ESCAPE("load failure for FPA");
+    }
+
+    pmChip *chip;                       // Chip from FPA
+    while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
+        psLogMsg ("ppbgrestoreLoop", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) {
+            continue;
+        }
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
+            ESCAPE("load failure for Chip");
+        }
+
+        // much of the following is adapted from ppImageSubtractBackground
+
+        if (chip->cells->n == 0) {
+            psError(PS_ERR_UNKNOWN, true, "Chip has no cells");
+            return false;
+        }
+
+        if (chip->cells->n > 1) {
+            psError(PS_ERR_UNKNOWN, true, "Chip has too many cells: %ld", chip->cells->n);
+            return false;
+        }
+        pmCell *cell = chip->cells->data[0]; // Cell of interest
+        if (!cell || !cell->process || !cell->file_exists) {
+            // Nothing to process
+            return false;
+        }
+        if (cell->readouts->n == 0) {
+            psError(PS_ERR_UNKNOWN, true, "Cell has no readouts");
+            return false;
+        }
+        if (cell->readouts->n > 1) {
+            psWarning("Cell has %ld readouts; only the first will be processed", cell->readouts->n);
+        }
+        pmReadout *ro = cell->readouts->data[0]; // Readout of interest
+        if (!ro || !ro->data_exists) {
+            psError(PS_ERR_UNKNOWN, true, "readout has no data");
+            return false;
+        }
+        psImage *image = ro->image;
+//        psImage *mask = NULL;
+//        psImageMaskType maskVal = 0;
+
+        pmFPAview roView = *view;
+        roView.cell = 0;
+        roView.readout = 0;
+        pmReadout *modelRO = pmFPAviewThisReadout(&roView, backmdl->fpa);
+        if (!modelRO || !modelRO->data_exists) {
+            psError(PS_ERR_UNKNOWN, true, "model readout has no data");
+            return false;
+        }
+        output->save = true;
+
+#ifdef notdef
+        psImageBinning *binning = psMetadataLookupPtr(&status, modelRO->analysis,
+                                                  "PSPHOT.BACKGROUND.BINNING"); // Binning for model
+#endif
+        psImageBinning *binning = psphotBackgroundBinning(image, config);
+        if (!binning) {
+            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find background binning");
+            return false;
+        }
+        pmReadout *background = pmFPAfileDefineInternal (config->files, "PSPHOT.BACKGND", image->numCols, image->numRows, PS_TYPE_F32);
+
+        // linear interpolation to full-scale
+        if (!psImageUnbin (background->image, modelRO->image, binning)) {
+            psError (PSPHOT_ERR_PROG, true, "inconsistent sizes for unbinning");
+            return false;
+        }
+        psF32 **backData = background->image->data.F32;
+
+        // Do the background subtraction
+        int numCols = image->numCols, numRows = image->numRows; // Size of image
+        long nancount = 0;
+        long finitecount = 0;
+        for (int y = 0; y < numRows; y++) {
+            for (int x = 0; x < numCols; x++) {
+                float value = backData[y][x];
+                if (!isfinite(value)) {
+                    // if background is NAN leave the image unchanged
+                    // According to ppImageSubtractBackground pixels where the background is not finite should be NAN
+                    // experimentally
+                    // for breakpoint
+                    float imageval =  image->data.F32[y][x] ;
+                    nancount++;
+                    if (isfinite(imageval)) {
+                         finitecount++;
+                         //   psWarning("unexpected finite image value %f found at %d %d background is infinite", imageval, x, y);
+                    }
+                    //      Doing this is causes a lot of new NAN pixels to appear.
+                    //      NANS are appearing in the model for some reason.
+                    //      image->data.F32[y][x] = NAN;
+                } else {
+                    // XXX: TODO:following ppImage we should not modify pixels that are masked.
+                    image->data.F32[y][x] += value;
+                }
+            }
+        }
+        if (nancount) {
+            psWarning("%ld infinite pixels found in background %ld pixels were finite\n", nancount, finitecount);
+        }
+        pmFPAfileDropInternal(config->files, "PSPHOT.BACKGND");
+
+        // Close chip
+        if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+            ESCAPE("save failure for Chip");
+        }
+    }
+
+    if (psTraceGetLevel("ppbgrestore") >= 3) {
+//        ppbgrestoreFileCheck(config);
+    }
+
+    // Output and Close FPA
+    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
+        ESCAPE("save failure for FPA");
+    }
+    psFree(view);
+
+    return true;
+}
Index: trunk/ppbgrestore/src/ppbgrestoreParseCamera.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreParseCamera.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreParseCamera.c	(revision 25972)
@@ -0,0 +1,31 @@
+#include "ppbgrestore.h"
+
+ppbgrestoreOptions *ppbgrestoreParseCamera(pmConfig *config)
+{
+    ppbgrestoreOptions *options = psAlloc(sizeof(*options));
+    bool status;
+
+    memset(options, 0, sizeof(*options));
+
+    pmFPAfile *input = pmFPAfileDefineFromArgs(&status, config, "PPBGRESTORE.INPUT", "INPUT");
+    if (!input) {
+        psFree(options);
+        psError(PS_ERR_UNKNOWN, false, "failed to define input file");
+        return NULL;
+    }
+    pmFPAfile *backmdl = pmFPAfileDefineFromArgs(&status, config, "PPBGRESTORE.BACKMDL", "BACKMDL");
+    if (!backmdl) {
+        psFree(options);
+        psError(PS_ERR_UNKNOWN, false, "failed to define background model file");
+        return NULL;
+    }
+    // pmFPAfile *outImage = pmFPAfileDefineOutput(config, input->fpa, "PPBGRESTORE.OUTPUT");
+    pmFPAfile *outImage = pmFPAfileDefineOutput(config, input->fpa, "PPBGRESTORE.OUTPUT");
+    if (!outImage) {
+        psError(PS_ERR_IO, false, _("Unable to generate output file from PPIMAGE.OUTPUT"));
+        psFree(options);
+        return NULL;
+    }
+
+    return options;
+}
Index: trunk/ppbgrestore/src/ppbgrestoreVersion.c
===================================================================
--- trunk/ppbgrestore/src/ppbgrestoreVersion.c	(revision 25972)
+++ trunk/ppbgrestore/src/ppbgrestoreVersion.c	(revision 25972)
@@ -0,0 +1,7 @@
+#include "ppbgrestore.h"
+
+void ppbgrestoreVersionPrint()
+{
+    // XXX: TODO
+    printf("version 0.0\n");
+}
