about summary refs log tree commit diff
path: root/generator/pbmtextps.c
diff options
context:
space:
mode:
Diffstat (limited to 'generator/pbmtextps.c')
-rw-r--r--generator/pbmtextps.c275
1 files changed, 173 insertions, 102 deletions
diff --git a/generator/pbmtextps.c b/generator/pbmtextps.c
index 08c77564..f879fa88 100644
--- a/generator/pbmtextps.c
+++ b/generator/pbmtextps.c
@@ -17,37 +17,27 @@
  */
 #define _XOPEN_SOURCE   /* Make sure popen() is in stdio.h */
 #define _BSD_SOURCE     /* Make sure stdrup() is in string.h */
+#include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include "pbm.h"
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
 #include "nstring.h"
 #include "shhopt.h"
+#include "pbm.h"
 
 
 #define BUFFER_SIZE 2048
 
-static const char *gs_exe_path = 
-#ifdef GHOSTSCRIPT_EXECUTABLE_PATH
-GHOSTSCRIPT_EXECUTABLE_PATH;
-#else
-0;
-#endif
-
-static const char *pnmcrop_exe_path = 
-#ifdef PNMCROP_EXECUTABLE_PATH
-PNMCROP_EXECUTABLE_PATH;
-#else
-0;
-#endif
-
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    int          res;         /* resolution, DPI */
-    int          fontsize;    /* Size of font in points */
+    unsigned int res;         /* resolution, DPI */
+    unsigned int fontsize;    /* Size of font in points */
     const char * font;      /* Name of postscript font */
     float        stroke;
         /* Width of stroke in points (only for outline font) */
@@ -58,26 +48,85 @@ struct cmdlineInfo {
 
 
 static void
+writeFileToStdout(const char * const fileName){
+    /* simple pbmtopbm */
+
+    FILE * ifP;
+    int format;
+    int cols, rows, row ;
+    unsigned char * bitrow; 
+    
+    ifP = pm_openr(fileName);
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    if (cols==0 || rows==0 || cols>INT_MAX-10 || rows>INT_MAX-10)
+      pm_error("Abnormal output from gs program.  "
+               "width x height = %u x %u", cols, rows);
+               
+    pbm_writepbminit(stdout, cols, rows, 0);           
+               
+    bitrow = pbm_allocrow_packed(cols);
+    
+    for (row = 0; row < rows; ++row) {
+        pbm_readpbmrow_packed(ifP, bitrow, cols, format);
+        pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+    }
+    pbm_freerow_packed(bitrow);
+}
+
+
+
+static void
+buildTextFromArgs(int           const argc,
+                  char **       const argv,
+                  const char ** const textP) {
+
+    char * text;
+    unsigned int totalTextSize;
+    unsigned int i;
+
+    text = strdup("");
+    totalTextSize = 1;
+
+    for (i = 1; i < argc; ++i) {
+        if (i > 1) {
+            totalTextSize += 1;
+            text = realloc(text, totalTextSize);
+            if (text == NULL)
+                pm_error("out of memory");
+            strcat(text, " ");
+        } 
+        totalTextSize += strlen(argv[i]);
+        text = realloc(text, totalTextSize);
+        if (text == NULL)
+            pm_error("out of memory");
+        strcat(text, argv[i]);
+    }
+    *textP = text;
+}
+
+
+
+static void
 parseCommandLine(int argc, char ** argv,
                  struct cmdlineInfo *cmdlineP) {
 /*---------------------------------------------------------------------------
   Note that the file spec array we return is stored in the storage that
   was passed to us as the argv array.
 ---------------------------------------------------------------------------*/
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
     /* Instructions to OptParseOptions2 on how to parse our options.
    */
     optStruct3 opt;
 
     unsigned int option_def_index;
-    int i;
-    char * text;
-    int totaltextsize = 0;
+
+    MALLOCARRAY(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENTRY */
-    OPTENT3(0, "resolution", OPT_INT,    &cmdlineP->res,            NULL,  0);
+    OPTENT3(0, "resolution", OPT_UINT,   &cmdlineP->res,            NULL,  0);
     OPTENT3(0, "font",       OPT_STRING, &cmdlineP->font,           NULL,  0);
-    OPTENT3(0, "fontsize",   OPT_INT,    &cmdlineP->fontsize,       NULL,  0);
+    OPTENT3(0, "fontsize",   OPT_UINT,   &cmdlineP->fontsize,       NULL,  0);
     OPTENT3(0, "stroke",     OPT_FLOAT,  &cmdlineP->stroke,         NULL,  0);
     OPTENT3(0, "verbose",    OPT_FLAG,   NULL, &cmdlineP->verbose,         0);
 
@@ -93,48 +142,43 @@ parseCommandLine(int argc, char ** argv,
 
     optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
 
-    text = strdup("");
-    totaltextsize = 1;
-
-    for (i = 1; i < argc; i++) {
-        if (i > 1) {
-            totaltextsize += 1;
-            text = realloc(text, totaltextsize);
-            if (text == NULL)
-                pm_error("out of memory");
-            strcat(text, " ");
-        } 
-        totaltextsize += strlen(argv[i]);
-        text = realloc(text, totaltextsize);
-        if (text == NULL)
-            pm_error("out of memory");
-        strcat(text, argv[i]);
-    }
-    cmdlineP->text = text;
+    buildTextFromArgs(argc, argv, &cmdlineP->text);
 }
 
 
 
 static const char *
-construct_postscript(struct cmdlineInfo const cmdl) {
+construct_postscript(struct cmdlineInfo const cmdline) {
 
     const char * retval;
     const char * template;
 
-    if (cmdl.stroke <= 0) 
-        template = "/%s findfont\n%d scalefont\nsetfont\n12 36 moveto\n"
-            "(%s) show\nshowpage\n";
+    if (cmdline.stroke < 0) 
+        template =
+            "/%s findfont\n"
+            "%d scalefont\n"
+            "setfont\n"
+            "12 36 moveto\n"
+            "(%s) show\n"
+            "showpage\n";
     else 
-        template = "/%s findfont\n%d scalefont\nsetfont\n12 36 moveto\n"
-            "%f setlinewidth\n0 setgray\n"
-            "(%s) true charpath\nstroke\nshowpage\n";
-
-    if (cmdl.stroke < 0)
-        asprintfN(&retval, template, cmdl.font, cmdl.fontsize, 
-                  cmdl.text);
+        template =
+            "/%s findfont\n"
+            "%d scalefont\n"
+            "setfont\n"
+            "12 36 moveto\n"
+            "%f setlinewidth\n"
+            "0 setgray\n"
+            "(%s) true charpath\n"
+            "stroke\n"
+            "showpage\n";
+
+    if (cmdline.stroke < 0)
+        asprintfN(&retval, template, cmdline.font, cmdline.fontsize, 
+                  cmdline.text);
     else
-        asprintfN(&retval, template, cmdl.font, cmdl.fontsize, 
-                  cmdl.stroke, cmdl.text);
+        asprintfN(&retval, template, cmdline.font, cmdline.fontsize, 
+                  cmdline.stroke, cmdline.text);
 
     return retval;
 }
@@ -142,24 +186,27 @@ construct_postscript(struct cmdlineInfo const cmdl) {
 
 
 static const char *
-gs_executable_name()
-{
+gsExecutableName() {
+
+    const char * const which = "which gs";
+
     static char buffer[BUFFER_SIZE];
-    if(! gs_exe_path) {
-        const char * const which = "which gs";
-        FILE *f;
-        memset(buffer, 0, BUFFER_SIZE);
-        if(!(f = popen(which, "r")))
-            pm_error("Can't find ghostscript");
-        fread(buffer, 1, BUFFER_SIZE, f);
-        if(buffer[strlen(buffer) - 1] == '\n')
-            buffer[strlen(buffer) - 1] = 0;
-        pclose(f);
-        if(buffer[0] != '/' && buffer[0] != '.')
-            pm_error("Can't find ghostscript");
-    }
-    else
-        strcpy(buffer, gs_exe_path);
+
+    FILE * f;
+
+    memset(buffer, 0, BUFFER_SIZE);
+
+    f = popen(which, "r");
+    if (!f)
+        pm_error("Can't find ghostscript");
+
+    fread(buffer, 1, BUFFER_SIZE, f);
+    if (buffer[strlen(buffer) - 1] == '\n')
+        buffer[strlen(buffer) - 1] = '\0';
+    pclose(f);
+    
+    if (buffer[0] != '/' && buffer[0] != '.')
+        pm_error("Can't find ghostscript");
 
     return buffer;
 }
@@ -167,30 +214,33 @@ gs_executable_name()
 
 
 static const char *
-crop_executable_name()
-{
+cropExecutableName(void) {
+
+    const char * const which = "which pnmcrop";
+
     static char buffer[BUFFER_SIZE];
-    if(! pnmcrop_exe_path) {
-        const char * const which = "which pnmcrop";
-        FILE *f;
-        memset(buffer, 0, BUFFER_SIZE);
-        if(!(f = popen(which, "r"))) {
-            return 0;
-        }
-    
+    const char * retval;
+
+    FILE * f;
+
+    memset(buffer, 0, BUFFER_SIZE);
+
+    f = popen(which, "r");
+    if (!f)
+        retval = NULL;
+    else {
         fread(buffer, 1, BUFFER_SIZE, f);
-        if(buffer[strlen(buffer) - 1] == '\n')
+        if (buffer[strlen(buffer) - 1] == '\n')
             buffer[strlen(buffer) - 1] = 0;
         pclose(f);
-        if(buffer[0] != '/' && buffer[0] != '.') {
-            buffer[0] = 0;
+            
+        if (buffer[0] != '/' && buffer[0] != '.') {
+            retval = NULL;
             pm_message("Can't find pnmcrop");
-        }
+        } else
+            retval = buffer;
     }
-    else
-        strcpy(buffer, pnmcrop_exe_path);
-
-    return buffer;
+    return retval;
 }
 
 
@@ -201,12 +251,33 @@ gsCommand(const char *       const psFname,
           struct cmdlineInfo const cmdline) {
 
     const char * retval;
-    int const x = cmdline.res * 11;
-    int const y = cmdline.res * (cmdline.fontsize * 2 + 72)  / 72.;
+    double const x = (double) cmdline.res * 11;
+    double const y = (double) cmdline.res * 
+                     ((double) cmdline.fontsize * 2 + 72)  / 72;
+    
+    if (cmdline.res <= 0)
+         pm_error("Resolution (dpi) must be positive.");
+    
+    if (cmdline.fontsize <= 0)
+         pm_error("Font size must be positive.");
+    
+    /* The following checks are for guarding against overflows in this 
+       function.  Huge x,y values that pass these checks may be
+       rejected by the 'gs' program.
+    */
+    
+    if (x > (double) INT_MAX-10)
+         pm_error("Absurdly fine resolution: %u. Output width too large.",
+                   cmdline.res );
+    if (y > (double) INT_MAX-10)
+         pm_error("Absurdly fine resolution (%u) and/or huge font size (%u). "
+                  "Output height too large.", cmdline.res, cmdline.fontsize);
+         
     asprintfN(&retval, "%s -g%dx%d -r%d -sDEVICE=pbm "
               "-sOutputFile=%s -q -dBATCH -dNOPAUSE %s </dev/null >/dev/null", 
-              gs_executable_name(), x, y, cmdline.res, 
+              gsExecutableName(), (int) x, (int) y, cmdline.res, 
               outputFilename, psFname);
+
     return retval;
 }
 
@@ -216,11 +287,12 @@ static const char *
 cropCommand(const char * const inputFileName) {
 
     const char * retval;
+    const char * plainOpt = pm_plain_output ? "-plain" : "" ;
     
-    if (crop_executable_name()) {
-        asprintfN(&retval, "%s -top -right %s", 
-                  crop_executable_name(), inputFileName);
-        if (retval == NULL)
+    if (cropExecutableName()) {
+        asprintfN(&retval, "%s -top -right %s %s", 
+                  cropExecutableName(), plainOpt, inputFileName);
+        if (retval == strsol)
             pm_error("Unable to allocate memory");
     } else
         retval = NULL;
@@ -234,7 +306,7 @@ static void
 writeProgram(const char *       const psFname,
              struct cmdlineInfo const cmdline) {
 
-    const char *ps;
+    const char * ps;
     FILE * psfile;
 
     psfile = fopen(psFname, "w");
@@ -288,14 +360,13 @@ cropToStdout(const char * const inputFileName,
     const char * com;
 
     com = cropCommand(inputFileName);
+
     if (com == NULL) {
         /* No pnmcrop.  So don't crop. */
         pm_message("Can't find pnmcrop command, image will be large");
-        asprintfN(&com, "cat %s", inputFileName);
-        if (com == NULL) 
-            pm_error("Unable to allocate memory.");
+        writeFileToStdout(inputFileName);
     } else {
-        FILE *pnmcrop;
+        FILE * pnmcrop;
 
         if (verbose)
             pm_message("Running crop command '%s'", com);
@@ -326,8 +397,8 @@ cropToStdout(const char * const inputFileName,
             }
             fclose(pnmcrop);
         }
+        strfree(com);
     }
-    strfree(com);
 }