From a8d5d87e6783f0c686b60c86ad1cb44443871ea9 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Fri, 12 Aug 2011 02:51:32 +0000 Subject: Add pamexec git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1533 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- other/Makefile | 2 +- other/pamexec.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 other/pamexec.c (limited to 'other') 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 +#include +#include + +#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; +} + + + -- cgit 1.4.1