about summary refs log tree commit diff
path: root/other
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2011-08-12 02:51:32 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2011-08-12 02:51:32 +0000
commita8d5d87e6783f0c686b60c86ad1cb44443871ea9 (patch)
treee0c787022ca7ce8899ef1cb0df2bed3423fa4b04 /other
parentd232ba913442f0f34b102160688bc8a705388e57 (diff)
downloadnetpbm-mirror-a8d5d87e6783f0c686b60c86ad1cb44443871ea9.tar.gz
netpbm-mirror-a8d5d87e6783f0c686b60c86ad1cb44443871ea9.tar.xz
netpbm-mirror-a8d5d87e6783f0c686b60c86ad1cb44443871ea9.zip
Add pamexec
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1533 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'other')
-rw-r--r--other/Makefile2
-rw-r--r--other/pamexec.c192
2 files changed, 193 insertions, 1 deletions
diff --git a/other/Makefile b/other/Makefile
index a6748347..f2690e05 100644
--- a/other/Makefile
+++ b/other/Makefile
@@ -24,7 +24,7 @@ endif
 # build.
 
 PORTBINARIES = pamarith pambayer pamchannel pamdepth \
-	pamendian pamfixtrunc pamlookup pampick pamsplit \
+	pamendian pamexec pamfixtrunc pamlookup pampick pamsplit \
 	pamstack pamsummcol pnmcolormap \
 	ppmdcfont ppmddumpfont ppmdmkfont 
 
diff --git a/other/pamexec.c b/other/pamexec.c
new file mode 100644
index 00000000..5961319b
--- /dev/null
+++ b/other/pamexec.c
@@ -0,0 +1,192 @@
+/******************************************************************************
+                               pamexec
+*******************************************************************************
+  Split a Netpbm format input file into multiple Netpbm format output streams
+  with one image per output stream and pipe this into the specified command.
+
+  By Bryan Henderson, Olympia WA; June 2000
+  and Michael Pot, New Zealand, August 2011
+
+  Contributed to the public domain by its authors.
+
+******************************************************************************/
+
+#define _BSD_SOURCE 1      /* Make sure strdup() is in string.h */
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "pm_c_util.h"
+#include "shhopt.h"
+#include "nstring.h"
+#include "mallocvar.h"
+#include "pam.h"
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * command;
+    const char * inputFileName;
+    unsigned int debug;
+    unsigned int check;
+};
+
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the pointers we place into *cmdlineP are sometimes to storage
+   in the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry *option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "debug",   OPT_FLAG,   NULL,         &cmdlineP->debug, 0);
+    OPTENT3(0,   "check",   OPT_FLAG,   NULL,         &cmdlineP->check, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;   /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 < 1) 
+        pm_error("You must specify at least one argument: the shell command "
+                 "to execute");
+    else {
+        cmdlineP->command = argv[1];
+
+        if (argc-1 < 2)
+            cmdlineP->inputFileName = "-";
+        else {
+            cmdlineP->inputFileName = argv[2];
+
+            if (argc-1 > 2)
+                pm_error("Too many arguments.  There are at most two: "
+                         "command and input file name");
+        }
+    }
+}
+
+
+
+static void
+pipeOneImage(FILE * const infileP,
+             FILE * const outfileP) {
+
+    struct pam inpam;
+    struct pam outpam;
+    enum pm_check_code checkRetval;
+    
+    unsigned int row;
+    tuple * tuplerow;
+
+    pnm_readpaminit(infileP, &inpam, PAM_STRUCT_SIZE(tuple_type));
+
+    pnm_checkpam(&inpam, PM_CHECK_BASIC, &checkRetval);
+
+    outpam = inpam;
+    outpam.file = outfileP;
+
+    pnm_writepaminit(&outpam);
+
+    tuplerow = pnm_allocpamrow(&inpam);
+
+    for (row = 0; row < inpam.height; ++row) {
+        pnm_readpamrow(&inpam, tuplerow);
+        pnm_writepamrow(&outpam, tuplerow);
+    }
+
+    pnm_freepamrow(tuplerow);
+}
+
+
+
+static void
+doOneImage(FILE *        const ifP,
+           const char *  const command,
+           bool          const check,
+           const char ** const errorP) {
+/*----------------------------------------------------------------------------
+   Run command 'command' on the next image in stream *ifP.
+
+   Return as *errorP a text explanation of how we failed, or NULL if we
+   didn't.
+-----------------------------------------------------------------------------*/
+    FILE * ofP;
+
+    ofP = popen(command, "w");
+
+    if (ofP == NULL)
+        pm_asprintf(errorP, 
+                    "Failed to start shell to run command '%s'.  "
+                    "errno = %d (%s)",
+                    command, errno, strerror(errno));
+    else {
+        int rc;
+
+        pipeOneImage(ifP, ofP);
+            
+        rc = pclose(ofP);
+
+        if (check && rc != 0)
+            pm_asprintf(errorP, "Command '%s' terminated abnormally "
+                        "or with nonzero exit status", command);
+        else
+            *errorP = NULL;
+    }
+}
+
+
+
+int
+main(int argc, const char *argv[]) {
+
+    struct cmdlineInfo cmdline;
+
+    FILE *       ifP;         /* Input file pointer */
+    bool         eof;         /* No more images in input */
+    unsigned int imageSeq;
+        /* Sequence number of current image in input file.  First = 0.
+           (Useful for tracking down problems).
+        */
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+    
+    ifP = pm_openr(cmdline.inputFileName);
+
+    for (eof = FALSE, imageSeq = 0; !eof; ++imageSeq) {
+        const char * error;
+        
+        doOneImage(ifP, cmdline.command, cmdline.check, &error);
+
+        if (error) {
+            pm_error("Failed on image %u: %s", imageSeq, error);
+            pm_strfree(error);
+        }
+
+        pnm_nextimage(ifP, &eof);
+    }
+    pm_close(ifP);
+    
+    return 0;
+}
+
+
+