"Fossies" - the Fresh Open Source Software Archive

Member "foomatic-filters-4.0-20160212/fileconverter.c" (12 Feb 2016, 8463 Bytes) of package /linux/misc/foomatic-filters-4.0-20160212.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fileconverter.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.0.17_vs_4.0-20160212.

    1 /* fileconverter.c
    2  *
    3  * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
    4  * Copyright (C) 2008 Lars Uebernickel <larsuebernickel@gmx.de>
    5  *
    6  * This file is part of foomatic-rip.
    7  *
    8  * Foomatic-rip is free software; you can redistribute it and/or modify
    9  * it under the terms of the GNU General Public License as published by
   10  * the Free Software Foundation; either version 2 of the License, or
   11  * (at your option) any later version.
   12  *
   13  * Foomatic-rip is distributed in the hope that it will be useful, but
   14  * WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16  * General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU Lesser General Public
   19  * License along with this library; if not, write to the
   20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   21  * Boston, MA 02111-1307, USA.
   22  */
   23 
   24 #include <stdlib.h>
   25 #include <stdio.h>
   26 #include <string.h>
   27 #include <signal.h>
   28 #include <unistd.h>
   29 
   30 #include "foomaticrip.h"
   31 #include "options.h"
   32 #include "process.h"
   33 
   34 
   35 /*
   36  * One of these fileconverters is used if the 'textfilter' option in the config file
   37  * is not set. (Except if the spooler is CUPS, then 'texttops' is used
   38  */
   39 const char *fileconverters[][2] = {
   40     { "a2ps", "a2ps -1 @@--medium=@@PAGESIZE@@ @@--center-title=@@JOBTITLE@@ -o -" },
   41     { "enscript", "enscript -G @@-M @@PAGESIZE@@ @@-b \"Page $%|@@JOBTITLE@@ --margins=36:36:36:36 --mark-wrapped-lines=arrow --word-wrap -p-" },
   42     { "mpage", "mpage -o -1 @@-b @@PAGESIZE@@ @@-H -h @@JOBTITLE@@ -m36l36b36t36r -f -P- -" },
   43     { "paps", "paps @@--paper @@PAGESIZE@@ --header --font=11.5" },
   44     { NULL, NULL }
   45 };
   46 
   47 char fileconverter[PATH_MAX] = "";
   48 
   49 void set_fileconverter(const char *fc)
   50 {
   51     int i;
   52     for (i = 0; fileconverters[i][0]; i++) {
   53       if (!strcmp(fc, fileconverters[i][0])) {
   54             strlcpy(fileconverter, fileconverters[i][1], PATH_MAX);
   55         break;
   56       }
   57     }
   58     if (!fileconverters[i][0])
   59         strlcpy(fileconverter, fc, PATH_MAX);
   60 }
   61 
   62 int guess_fileconverter()
   63 {
   64     int i;
   65     for (i = 0; fileconverters[i][0]; i++) {
   66         if (find_in_path(fileconverters[i][0], getenv("PATH"), NULL)) {
   67             strlcpy(fileconverter, fileconverters[i][1], PATH_MAX);
   68             return 1;
   69         }
   70     }
   71     return 0;
   72 }
   73 
   74 /*
   75  * Replace @@...@@PAGESIZE@@ and @@...@@JOBTITLE@@ with 'pagesize' and
   76  * 'jobtitle' (if they are are not NULL). Returns a newly malloced string.
   77  */
   78 char * fileconverter_from_template(const char *fileconverter,
   79         const char *pagesize, const char *jobtitle)
   80 {
   81     char *templstart, *templname;
   82     const char *last = fileconverter;
   83     char *res;
   84     size_t len;
   85 
   86     len = strlen(fileconverter) +
   87             (pagesize ? strlen(pagesize) : 0) + 
   88             (jobtitle ? strlen(jobtitle) : 0) +1;
   89     res = malloc(len);
   90     res[0] = '\0';
   91 
   92     while ((templstart = strstr(last, "@@"))) {
   93         strncat(res, last, templstart - last);
   94         templstart += 2;
   95         templname = strstr(templstart, "@@");
   96         if (!templname)
   97             break;
   98         if (startswith(templname, "@@PAGESIZE@@") && pagesize) {
   99             strncat(res, templstart, templname - templstart);
  100             strcat(res, pagesize);
  101             last = templname + 12;
  102         }
  103         else if (startswith(templname, "@@JOBTITLE@@") && jobtitle) {
  104             strncat(res, templstart, templname - templstart);
  105             strcat(res, jobtitle);
  106             while (templstart != templname) {
  107                 if (*templstart == '\"') {
  108                     strcat(res, "\"");
  109                     break;
  110                 }
  111                 templstart++;
  112             }
  113             last = templname + 12;
  114         }
  115         else
  116             last += strlen(res);
  117     }
  118     strlcat(res, last, len);
  119 
  120     return res;
  121 }
  122 
  123 int exec_kid2(FILE *in, FILE *out, void *user_arg)
  124 {
  125     int n;
  126     const char *alreadyread = (const char *)user_arg;
  127     char tmp[1024];
  128 
  129     /* child, first part of the pipe, reading in the data from standard input
  130      * and stuffing it into the file converter after putting in the already
  131      * read data (in alreadyread) */
  132 
  133     _log("kid2: writing alreadyread\n");
  134 
  135     /* At first pass the data which we already read to the filter */
  136     fwrite(alreadyread, 1, strlen(alreadyread), out);
  137 
  138     _log("kid2: Then read the rest from standard input\n");
  139     /* Then read the rest from standard input */
  140     while ((n = fread(tmp, 1, 1024, stdin)) > 0)
  141         fwrite(tmp, 1, n, out);
  142 
  143     _log("kid2: Close out and stdin\n");
  144     fclose(out);
  145     fclose(stdin);
  146 
  147     _log("kid2 finished\n");
  148     return EXIT_PRINTED;
  149 }
  150 
  151 typedef struct {
  152     const char *fileconv;
  153     const char *alreadyread;
  154 } kid1_userdata_t;
  155 
  156 int exec_kid1(FILE *in, FILE *out, void *user_arg)
  157 {
  158     int kid2;
  159     FILE *kid2out;
  160     int status;
  161     const char *fileconv = ((kid1_userdata_t *)user_arg)->fileconv;
  162     const char *alreadyread = ((kid1_userdata_t *)user_arg)->alreadyread;
  163 
  164     kid2 = start_process("kid2", exec_kid2, (void *)alreadyread, NULL, &kid2out);
  165     if (kid2 < 0)
  166         return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
  167 
  168     if (spooler != SPOOLER_CUPS)
  169         _log("file converter command: %s\n", fileconv);
  170 
  171     if (dup2(fileno(kid2out), fileno(stdin)) < 0) {
  172         _log("kid1: Could not dup stdin\n");
  173         fclose(kid2out);
  174         return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
  175     }
  176     if (dup2(fileno(out), fileno(stdout)) < 0) {
  177         _log("kid1: Could not dup stdout\n");
  178         fclose(kid2out);
  179         return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
  180     }
  181     if (debug && !redirect_log_to_stderr()) {
  182         _log("Could not dup logh to stderr\n");
  183         fclose(kid2out);
  184         return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
  185     }
  186 
  187     /* Actually run the thing... */
  188     status = run_system_process("fileconverter", fileconv);
  189     fclose(out);
  190     fclose(kid2out);
  191     fclose(stdin);
  192     fclose(stdout);
  193 
  194     if (WIFEXITED(status)) {
  195         if (WEXITSTATUS(status) == 0) {
  196             wait_for_process(kid2);
  197             _log("kid1 finished\n");
  198             return EXIT_PRINTED;
  199         }
  200     }
  201     else if (WIFSIGNALED(status)) {
  202         switch (WTERMSIG(status)) {
  203             case SIGUSR1: return EXIT_PRNERR;
  204             case SIGUSR2: return EXIT_PRNERR_NORETRY;
  205             case SIGTTIN: return EXIT_ENGAGED;
  206         }
  207     }
  208     return EXIT_PRNERR;
  209 }
  210 
  211 
  212 /*
  213  *  This function is only used when the input data is not PostScript. Then it
  214  *  runs a filter which converts non-PostScript files into PostScript. The user
  215  *  can choose which filter he wants to use. The filter command line is
  216  *  provided by 'fileconverter'.
  217  */
  218 void get_fileconverter_handle(const char *alreadyread, FILE **fd, pid_t *pid)
  219 {
  220     pid_t kid1;
  221     FILE *kid1out;
  222     const char *pagesize;
  223     char *fileconv;
  224     kid1_userdata_t kid1_userdata;
  225 
  226     _log("\nStarting converter for non-PostScript files\n");
  227 
  228     if (isempty(fileconverter) && !guess_fileconverter())
  229         rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Cannot convert file to "
  230                 "Postscript (missing fileconverter).");
  231 
  232     /* Use wider margins so that the pages come out completely on every printer
  233      * model (especially HP inkjets) */
  234     pagesize = option_get_value(find_option("PageSize"), optionset("header"));
  235     if (pagesize && startswith(fileconverter, "a2ps")) {
  236         if (!strcasecmp(pagesize, "letter"))
  237             pagesize = "Letterdj";
  238         else if (!strcasecmp(pagesize, "a4"))
  239             pagesize = "A4dj";
  240     }
  241 
  242     if (do_docs)
  243         snprintf(get_current_job()->title, 128, "Documentation for the %s", printer_model);
  244 
  245     fileconv = fileconverter_from_template(fileconverter, pagesize, get_current_job()->title);
  246 
  247     kid1_userdata.fileconv = fileconv;
  248     kid1_userdata.alreadyread = alreadyread;
  249     kid1 = start_process("kid1", exec_kid1, &kid1_userdata, NULL, &kid1out);
  250     if (kid1 < 0)
  251         rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Cannot convert file to "
  252                 "Postscript (Cannot fork for kid1!)\n");
  253 
  254     *fd = kid1out;
  255     *pid = kid1;
  256 
  257     free(fileconv);
  258 }
  259 
  260 int close_fileconverter_handle(FILE *fileconverter_handle, pid_t fileconverter_pid)
  261 {
  262     int status;
  263 
  264     _log("\nClosing file converter\n");
  265     fclose(fileconverter_handle);
  266 
  267     status = wait_for_process(fileconverter_pid);
  268     if (WIFEXITED(status))
  269         return WEXITSTATUS(status);
  270     else
  271         return EXIT_PRNERR_NORETRY_BAD_SETTINGS;
  272 }
  273