diff options
Diffstat (limited to 'generator/pbmtextps.c')
-rw-r--r-- | generator/pbmtextps.c | 275 |
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); } |