"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