Index: trunk/ppConfigDump/src/ppConfigDump.c
===================================================================
--- trunk/ppConfigDump/src/ppConfigDump.c	(revision 12809)
+++ trunk/ppConfigDump/src/ppConfigDump.c	(revision 12827)
@@ -4,4 +4,5 @@
 
 #include <stdio.h>
+#include <string.h>
 #include <pslib.h>
 #include <psmodules.h>
@@ -23,4 +24,25 @@
 }
 
+void dump(const char *filename,     // Filename to which to dump
+          const char *description,  // Description of what's being dumped
+          psMetadata *md            // Metadata to dump
+          )
+{
+    if (!filename || strlen(filename) == 0) {
+        return;
+    }
+    if (strcmp(filename, "-") == 0) {
+        psString string = psMetadataConfigFormat(md); // String to dump
+        if (!string) {
+            psErrorStackPrint(stderr, "Can't write %s to STDOUT\n", description);
+            die(PS_EXIT_SYS_ERROR);
+        }
+        fprintf(stdout, "%s", string);
+        psFree(string);
+    } else if (!psMetadataConfigWrite(md, filename)) {
+        psErrorStackPrint(stderr, "Can't write %s to %s\n", description, filename);
+        die(PS_EXIT_SYS_ERROR);
+    }
+}
 
 int main(int argc, char *argv[])
@@ -39,19 +61,22 @@
 
     arguments = psMetadataAlloc();
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-file", 0,
-                     "FITS file to use for camera determination", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-site", 0,
-                     "Filename to dump site configuration", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-camera", 0,
-                     "Filename to dump camera configuration", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-format", 0,
-                     "Filename to dump camera format", NULL);
-    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-recipes", 0,
-                     "Filename to dump recipes", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-file", 0, "FITS file to use for camera determination", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-site", 0, "Filename for site configuration", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-camera", 0, "Filename for camera configuration", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-format", 0, "Filename for camera format", NULL);
+    psMetadataAddStr(arguments, PS_LIST_TAIL, "-dump-recipes", 0, "Filename for recipes", NULL);
+    psMetadata *recipeArgs = psMetadataAlloc(); // Options for dumping a single recipe
+    psMetadataAddStr(recipeArgs, PS_LIST_TAIL, "recipe", 0, "Name of recipe", NULL);
+    psMetadataAddStr(recipeArgs, PS_LIST_TAIL, "filename", 0, "Filename", NULL);
+    psMetadataAddMetadata(arguments, PS_LIST_TAIL, "-dump-recipe", 0, "Dump a single recipe", recipeArgs);
+    psFree(recipeArgs);
 
     if (argc == 1 || !psArgumentParse(arguments, &argc, argv)) {
         fprintf(stderr, "\nPan-STARRS IPP configuration dumper\n\n");
         fprintf(stderr, "Usage: %s [-file INPUT.fits] [-dump-site FILE.mdc]\n", argv[0]);
-        fprintf(stderr, "       [-dump-camera FILE.mdc] [-dump-format FILE.mdc] [-dump-recipe FILE.mdc]\n");
+        fprintf(stderr, "       [-dump-camera FILE.mdc] [-dump-format FILE.mdc] [-dump-recipes FILE.mdc]\n");
+        fprintf(stderr, "       [-dump-recipe RECIPE FILE.mdc]\n");
+        fprintf(stderr, "\n");
+        fprintf(stderr, "       FILE.mdc may be ""-"", in which case the file is written to stdout.\n");
         fprintf(stderr, "\n");
         psArgumentHelp(arguments);
@@ -86,27 +111,28 @@
 
     const char *siteName = psMetadataLookupStr(NULL, arguments, "-dump-site"); // Site filename
-    if (siteName && !psMetadataConfigWrite(config->site, siteName)) {
-        psErrorStackPrint(stderr, "Can't write site configuration to %s\n", siteName);
-        die(PS_EXIT_SYS_ERROR);
-    }
+    dump(siteName, "site configuration", config->site);
 
     const char *camName = psMetadataLookupStr(NULL, arguments, "-dump-camera"); // Camera filename
-    if (camName && !psMetadataConfigWrite(config->camera, camName)) {
-        psErrorStackPrint(stderr, "Can't write camera configuration to %s\n", camName);
-        die(PS_EXIT_SYS_ERROR);
-    }
+    dump(camName, "camera configuration", config->camera);
 
     const char *formatName = psMetadataLookupStr(NULL, arguments, "-dump-format"); // Format filename
-    if (formatName && !psMetadataConfigWrite(config->format, formatName)) {
-        psErrorStackPrint(stderr, "Can't write camera format to %s\n", formatName);
-        die(PS_EXIT_SYS_ERROR);
-    }
+    dump(formatName, "camera format", config->format);
 
-    const char *recipeName = psMetadataLookupStr(NULL, arguments, "-dump-recipes"); // Recipe filename
-    if (recipeName && !psMetadataConfigWrite(config->recipes, recipeName)) {
-        psErrorStackPrint(stderr, "Can't write recipes to %s\n", recipeName);
-        die(PS_EXIT_SYS_ERROR);
+    const char *recipesName = psMetadataLookupStr(NULL, arguments, "-dump-recipes"); // Recipes filename
+    dump(recipesName, "recipes", config->recipes);
+
+    recipeArgs = psMetadataLookupMetadata(NULL, arguments, "-dump-recipe");
+    const char *recipeName = psMetadataLookupStr(NULL, recipeArgs, "recipe"); // Name of recipe
+    if (recipeName) {
+        psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, recipeName); // Recipe desired
+        if (!recipe) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find recipe %s", recipeName);
+            die(PS_EXIT_CONFIG_ERROR);
+        }
+        const char *recipeFile = psMetadataLookupStr(NULL, recipeArgs, "filename"); // Filename for recipe
+        dump(recipeFile, "recipe", recipe);
     }
 
     die(PS_EXIT_SUCCESS);
 }
+
