void char_buffer::emit_troff_output(int device_format_selector) { // Handle output for BOTH html and image device formats // if `device_format_selector' is passed as // // HTML_FORMAT(HTML_OUTPUT_FILTER) // Buffer data is written to the output stream // with template image names translated to actual image names. // // HTML_FORMAT(IMAGE_OUTPUT_FILTER) // Buffer data is written to the output stream // with no translation, for image file creation in the post-processor. int idx = 0; char_block *element = head; while (element != NULL) write_upto_newline(&element, &idx, device_format_selector); #if 0 if (close(stdoutfd) < 0) sys_fatal ("close"); // now we grab fd=1 so that the next pipe cannot use fd=1 if (stdoutfd == 1) { if (dup(2) != stdoutfd) sys_fatal ("dup failed to use fd=1"); } #endif /* 0 */ }
int imageList::createPage(int pageno) { char *s; if (currentPageNo == pageno) return 0; if (currentPageNo >= 1) { /* * We need to unlink the files which change each time a new page is * processed. The final unlink is done by xtmpfile when pre-grohtml * exits. */ unlink(imagePageName); unlink(psPageName); } if (show_progress) { fprintf(stderr, "[%d] ", pageno); fflush(stderr); } #if defined(DEBUGGING) if (debug) fprintf(stderr, "creating page %d\n", pageno); #endif s = make_message("psselect -q -p%d %s %s\n", pageno, psFileName, psPageName); if (s == NULL) sys_fatal("make_message"); html_system(s, 1); s = make_message("echo showpage | " "%s%s -q -dBATCH -dSAFER " "-dDEVICEHEIGHTPOINTS=792 " "-dDEVICEWIDTHPOINTS=%d -dFIXEDMEDIA=true " "-sDEVICE=%s -r%d %s " "-sOutputFile=%s %s -\n", image_gen, EXE_EXT, (getMaxX(pageno) * image_res) / postscriptRes, image_device, image_res, antiAlias, imagePageName, psPageName); if (s == NULL) sys_fatal("make_message"); html_system(s, 1); free(s); currentPageNo = pageno; return 0; }
static int makeTempFiles(void) { #if defined(DEBUGGING) psFileName = DEBUG_FILE("prehtml-ps"); regionFileName = DEBUG_FILE("prehtml-region"); imagePageName = DEBUG_FILE("prehtml-page"); psPageName = DEBUG_FILE("prehtml-psn"); troffFileName = DEBUG_FILE("prehtml-troff"); htmlFileName = DEBUG_FILE("prehtml-html"); #else /* not DEBUGGING */ FILE *f; /* psPageName contains a single page of postscript */ f = xtmpfile(&psPageName, PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT, TRUE); if (f == NULL) { sys_fatal("xtmpfile"); return -1; } fclose(f); /* imagePageName contains a bitmap image of the single postscript page */ f = xtmpfile(&imagePageName, PAGE_TEMPLATE_LONG, PAGE_TEMPLATE_SHORT, TRUE); if (f == NULL) { sys_fatal("xtmpfile"); return -1; } fclose(f); /* psFileName contains a postscript file of the complete document */ f = xtmpfile(&psFileName, PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT, TRUE); if (f == NULL) { sys_fatal("xtmpfile"); return -1; } fclose(f); /* regionFileName contains a list of the images and their boxed coordinates */ f = xtmpfile(®ionFileName, REGION_TEMPLATE_LONG, REGION_TEMPLATE_SHORT, TRUE); if (f == NULL) { sys_fatal("xtmpfile"); return -1; } fclose(f); #endif /* not DEBUGGING */ return 0; }
static void set_redirection(int was, int willbe) { // Nothing to do if `was' and `willbe' already have same handle. if (was != willbe) { // Otherwise attempt the specified redirection. if (dup2 (willbe, was) < 0) { // Redirection failed, so issue diagnostic and bail out. fprintf(stderr, "failed to replace fd=%d with %d\n", was, willbe); if (willbe == STDOUT_FILENO) fprintf(stderr, "likely that stdout should be opened before %d\n", was); sys_fatal("dup2"); } // When redirection has been successfully completed assume redundant // handle `willbe' is no longer required, so close it. if (close(willbe) < 0) // Issue diagnostic if `close' fails. sys_fatal("close"); } }
pushBackBuffer::~pushBackBuffer () { if (charStack != 0) { free(charStack); } close(0); /* restore stdin in file descriptor 0 */ if (dup(stdIn) < 0) { sys_fatal("restore stdin"); } close(stdIn); }
static void writeNbytes(const char *s, int l) { int n = 0; int r; while (n < l) { r = write(stdoutfd, s, l - n); if (r < 0) sys_fatal("write"); n += r; s += r; } }
void imageList::createImage(imageItem *i) { if (i->X1 != -1) { char *s; int x1 = max(min(i->X1, i->X2) * image_res / postscriptRes - IMAGE_BOARDER_PIXELS, 0); int y1 = max(image_res * vertical_offset / 72 + min(i->Y1, i->Y2) * image_res / postscriptRes - IMAGE_BOARDER_PIXELS, 0); int x2 = max(i->X1, i->X2) * image_res / postscriptRes + IMAGE_BOARDER_PIXELS; int y2 = image_res * vertical_offset / 72 + max(i->Y1, i->Y2) * image_res / postscriptRes + 1 + IMAGE_BOARDER_PIXELS; if (createPage(i->pageNo) == 0) { s = make_message("pnmcut%s %d %d %d %d < %s " "| pnmcrop -quiet | pnmtopng%s %s > %s\n", EXE_EXT, x1, y1, x2 - x1 + 1, y2 - y1 + 1, imagePageName, EXE_EXT, TRANSPARENT, i->imageName); if (s == NULL) sys_fatal("make_message"); #if defined(DEBUGGING) if (debug) { fprintf(stderr, s); fflush(stderr); } #endif html_system(s, 0); free(s); } else { fprintf(stderr, "failed to generate image of page %d\n", i->pageNo); fflush(stderr); } #if defined(DEBUGGING) } else { if (debug) { fprintf(stderr, "ignoring image as x1 coord is -1\n"); fflush(stderr); } #endif } }
static void makeFileName(void) { if ((image_dir != NULL) && (strchr(image_dir, '%') != NULL)) { error("cannot use a `%%' within the image directory name"); exit(1); } if ((image_template != NULL) && (strchr(image_template, '%') != NULL)) { error("cannot use a `%%' within the image template"); exit(1); } if (image_dir == NULL) image_dir = (char *)""; else if (strlen(image_dir) > 0 && image_dir[strlen(image_dir) - 1] != '/') { image_dir = make_message("%s/", image_dir); if (image_dir == NULL) sys_fatal("make_message"); } if (image_template == NULL) macroset_template = make_message("%sgrohtml-%d", image_dir, (int)getpid()); else macroset_template = make_message("%s%s", image_dir, image_template); if (macroset_template == NULL) sys_fatal("make_message"); image_template = (char *)malloc(strlen("-%d") + strlen(macroset_template) + 1); if (image_template == NULL) sys_fatal("malloc"); strcpy(image_template, macroset_template); strcat(image_template, "-%d"); }
pushBackBuffer::pushBackBuffer (char *filename) { charStack = (char *)malloc(MAXPUSHBACKSTACK); if (charStack == 0) { sys_fatal("malloc"); } stackPtr = 0; /* index to push back stack */ debug = 0; verbose = 0; eofFound = FALSE; lineNo = 1; if (strcmp(filename, "") != 0) { stdIn = dup(0); if (stdIn < 0) { sys_fatal("dup stdin"); } close(0); if (open(filename, O_RDONLY) != 0) { sys_fatal("when trying to open file"); } else { fileName = filename; } } }
static int save_and_redirect(int was, int willbe) { if (was == willbe) // No redirection specified so don't do anything but silently bailing out. return (was); // Proceeding with redirection so first save and verify our duplicate // handle for `was'. int saved = dup(was); if (saved < 0) { fprintf(stderr, "unable to get duplicate handle for %d\n", was); sys_fatal("dup"); } // Duplicate handle safely established so complete redirection. set_redirection(was, willbe); // Finally return the saved duplicate descriptor for the // original `was' stream. return saved; }
int char_buffer::run_output_filter(int filter, int argc, char **argv) { int pipedes[2]; PID_T child_pid; int status; print_args(argc, argv); if (pipe(pipedes) < 0) sys_fatal("pipe"); #if MAY_FORK_CHILD_PROCESS // This is the UNIX process model. To invoke our post-processor, // we must `fork' the current process. if ((child_pid = fork()) < 0) sys_fatal("fork"); else if (child_pid == 0) { // This is the child process fork. We redirect its `stdin' stream // to read data emerging from our pipe. There is no point in saving, // since we won't be able to restore later! set_redirection(STDIN_FILENO, pipedes[0]); // The parent process will be writing this data, so we should release // the child's writeable handle on the pipe, since we have no use for it. if (close(pipedes[1]) < 0) sys_fatal("close"); // The IMAGE_OUTPUT_FILTER needs special output redirection... if (filter == IMAGE_OUTPUT_FILTER) { // with BOTH `stdout' AND `stderr' diverted to files. set_redirection(STDOUT_FILENO, PS_OUTPUT_STREAM); set_redirection(STDERR_FILENO, REGION_OUTPUT_STREAM); } // Now we are ready to launch the output filter. execvp(argv[0], argv); // If we get to here then the `exec...' request for the output filter // failed. Diagnose it and bail out. error("couldn't exec %1: %2", argv[0], strerror(errno), ((char *)0)); fflush(stderr); // just in case error() didn't exit(1); } else { // This is the parent process fork. We will be writing data to the // filter pipeline, and the child will be reading it. We have no further // use for our read handle on the pipe, and should close it. if (close(pipedes[0]) < 0) sys_fatal("close"); // Now we redirect the `stdout' stream to the inlet end of the pipe, // and push out the appropiately formatted data to the filter. pipedes[1] = save_and_redirect(STDOUT_FILENO, pipedes[1]); emit_troff_output(DEVICE_FORMAT(filter)); // After emitting all the data we close our connection to the inlet // end of the pipe so the child process will detect end of data. set_redirection(STDOUT_FILENO, pipedes[1]); // Finally, we must wait for the child process to complete. if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid) sys_fatal("wait"); } #elif MAY_SPAWN_ASYNCHRONOUS_CHILD // We do not have `fork', (or we prefer not to use it), // but asynchronous processes are allowed, passing data through pipes. // This should be ok for most Win32 systems and is preferred to `fork' // for starting child processes under Cygwin. // Before we start the post-processor we bind its inherited `stdin' // stream to the readable end of our pipe, saving our own `stdin' stream // in `pipedes[0]'. pipedes[0] = save_and_redirect(STDIN_FILENO, pipedes[0]); // for the Win32 model, // we need special provision for saving BOTH `stdout' and `stderr'. int saved_stdout = dup(STDOUT_FILENO); int saved_stderr = STDERR_FILENO; // The IMAGE_OUTPUT_FILTER needs special output redirection... if (filter == IMAGE_OUTPUT_FILTER) { // with BOTH `stdout' AND `stderr' diverted to files while saving a // duplicate handle for `stderr'. set_redirection(STDOUT_FILENO, PS_OUTPUT_STREAM); saved_stderr = save_and_redirect(STDERR_FILENO, REGION_OUTPUT_STREAM); } // We then use an asynchronous spawn request to start the post-processor. if ((child_pid = spawnvp(_P_NOWAIT, argv[0], argv)) < 0) { // Should the spawn request fail we issue a diagnostic and bail out. error("cannot spawn %1: %2", argv[0], strerror(errno), ((char *)0)); exit(1); } // Once the post-processor has been started we revert our `stdin' // to its original saved source, which also closes the readable handle // for the pipe. set_redirection(STDIN_FILENO, pipedes[0]); // if we redirected `stderr', for use by the image post-processor, // then we also need to reinstate its original assignment. if (filter == IMAGE_OUTPUT_FILTER) set_redirection(STDERR_FILENO, saved_stderr); // Now we redirect the `stdout' stream to the inlet end of the pipe, // and push out the appropiately formatted data to the filter. set_redirection(STDOUT_FILENO, pipedes[1]); emit_troff_output(DEVICE_FORMAT(filter)); // After emitting all the data we close our connection to the inlet // end of the pipe so the child process will detect end of data. set_redirection(STDOUT_FILENO, saved_stdout); // And finally, we must wait for the child process to complete. if (WAIT(&status, child_pid, _WAIT_CHILD) != child_pid) sys_fatal("wait"); #else /* can't do asynchronous pipes! */ // TODO: code to support an MS-DOS style process model // should go here #endif /* MAY_FORK_CHILD_PROCESS or MAY_SPAWN_ASYNCHRONOUS_CHILD */ return 0; }