int char_buffer::do_html(int argc, char *argv[]) { string s; alterDeviceTo(argc, argv, 0); argv += troff_arg; // skip all arguments up to groff argc -= troff_arg; argv = addZ(argc, argv); argc++; s = "-dwww-image-template="; s += macroset_template; // do not combine these statements, // otherwise they will not work s += '\0'; // the trailing `\0' is ignored argv = addRegDef(argc, argv, s.contents()); argc++; #if defined(DEBUGGING) # define HTML_DEBUG_STREAM OUTPUT_STREAM(htmlFileName) // slight security risk so only enabled if compiled with defined(DEBUGGING) if (debug) { int saved_stdout = save_and_redirect(STDOUT_FILENO, HTML_DEBUG_STREAM); emit_troff_output(DEVICE_FORMAT(HTML_OUTPUT_FILTER)); set_redirection(STDOUT_FILENO, saved_stdout); } #endif return run_output_filter(HTML_OUTPUT_FILTER, argc, argv); }
int char_buffer::do_image(int argc, char *argv[]) { string s; alterDeviceTo(argc, argv, 1); argv += troff_arg; // skip all arguments up to troff/groff argc -= troff_arg; argv = addRegDef(argc, argv, "-rps4html=1"); argc++; s = "-dwww-image-template="; s += macroset_template; s += '\0'; argv = addRegDef(argc, argv, s.contents()); argc++; // override local settings and produce a page size letter postscript file argv = addRegDef(argc, argv, "-P-pletter"); argc++; #if defined(DEBUGGING) # define IMAGE_DEBUG_STREAM OUTPUT_STREAM(troffFileName) // slight security risk so only enabled if compiled with defined(DEBUGGING) if (debug) { int saved_stdout = save_and_redirect(STDOUT_FILENO, IMAGE_DEBUG_STREAM); emit_troff_output(DEVICE_FORMAT(IMAGE_OUTPUT_FILTER)); set_redirection(STDOUT_FILENO, saved_stdout); } #endif return run_output_filter(IMAGE_OUTPUT_FILTER, argc, argv); }
int get_new_command(char *mes) { int redir = 0, i, res; char *name; term_def_t *term; if (debug_flag) printf("get_new_command:\n"); term = get_next_term(); if ((term == NULL) || (term->term_type != CMD_TERM)) cmd_parser(mes, 0, 1, &redir); else { unget_term(); redir = check_cmd_for_redirect(); }; if (redir != 0) { for (i = 0; i < term_count; i++) { if (terms[i].term_type == CMD_REDIR_TERM) break; }; if (i >= term_count - 1) { printf("Syntax error:\n%s\n", cmd_line); go_to_dialog(); return(3); }; if (terms[i + 1].term_type != ITEM_TERM) { printf("Syntax error:\n%s\n", cmd_line); go_to_dialog(); return(3); }; name = terms[i + 1].term; res = set_redirection(name, redir); if (res != 0) { printf("Command failed:\n%s\n", cmd_line); go_to_dialog(); return(3); }; res = run_command(); remove_reditection(); return(res); }; res = run_command(); return(res); }
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; }