]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/pdftops.c
Merge changes from CUPS 1.4svn-r8305.
[thirdparty/cups.git] / filter / pdftops.c
1 /*
2 * "$Id$"
3 *
4 * PDF to PostScript filter front-end for the Common UNIX Printing
5 * System (CUPS).
6 *
7 * Copyright 2007-2009 by Apple Inc.
8 * Copyright 1997-2006 by Easy Software Products.
9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
15 *
16 * Contents:
17 *
18 * main() - Main entry for filter...
19 * cancel_job() - Flag the job as canceled.
20 */
21
22 /*
23 * Include necessary headers...
24 */
25
26 #include <cups/cups.h>
27 #include <cups/string.h>
28 #include <cups/i18n.h>
29 #include <signal.h>
30 #include <sys/wait.h>
31 #include <errno.h>
32
33
34 /*
35 * Local functions...
36 */
37
38 static void cancel_job(int sig);
39
40
41 /*
42 * Local globals...
43 */
44
45 static int job_canceled = 0;
46
47
48 /*
49 * 'main()' - Main entry for filter...
50 */
51
52 int /* O - Exit status */
53 main(int argc, /* I - Number of command-line args */
54 char *argv[]) /* I - Command-line arguments */
55 {
56 int fd; /* Copy file descriptor */
57 char *filename, /* PDF file to convert */
58 tempfile[1024]; /* Temporary file */
59 char buffer[8192]; /* Copy buffer */
60 int bytes; /* Bytes copied */
61 int num_options; /* Number of options */
62 cups_option_t *options; /* Options */
63 const char *val; /* Option value */
64 int orientation, /* Output orientation */
65 fit; /* Fit output to default page size? */
66 ppd_file_t *ppd; /* PPD file */
67 ppd_size_t *size; /* Current page size */
68 int pdfpid, /* Process ID for pdftops */
69 pdfwaitpid, /* Process ID from wait() */
70 pdfstatus, /* Status from pdftops */
71 pdfargc; /* Number of args for pdftops */
72 char *pdfargv[100], /* Arguments for pdftops/gs */
73 pdfwidth[255], /* Paper width */
74 pdfheight[255]; /* Paper height */
75 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
76 struct sigaction action; /* Actions for POSIX signals */
77 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
78
79
80 /*
81 * Make sure status messages are not buffered...
82 */
83
84 setbuf(stderr, NULL);
85
86 /*
87 * Make sure we have the right number of arguments for CUPS!
88 */
89
90 if (argc < 6 || argc > 7)
91 {
92 _cupsLangPrintf(stderr,
93 _("Usage: %s job user title copies options [filename]\n"),
94 argv[0]);
95 return (1);
96 }
97
98 /*
99 * Register a signal handler to cleanly cancel a job.
100 */
101
102 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
103 sigset(SIGTERM, cancel_job);
104 #elif defined(HAVE_SIGACTION)
105 memset(&action, 0, sizeof(action));
106
107 sigemptyset(&action.sa_mask);
108 action.sa_handler = cancel_job;
109 sigaction(SIGTERM, &action, NULL);
110 #else
111 signal(SIGTERM, cancel_job);
112 #endif /* HAVE_SIGSET */
113
114 /*
115 * Copy stdin if needed...
116 */
117
118 if (argc == 6)
119 {
120 /*
121 * Copy stdin to a temp file...
122 */
123
124 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
125 {
126 _cupsLangPrintError(_("ERROR: Unable to copy PDF file"));
127 return (1);
128 }
129
130 fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
131 tempfile);
132
133 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
134 write(fd, buffer, bytes);
135
136 close(fd);
137
138 filename = tempfile;
139 }
140 else
141 {
142 /*
143 * Use the filename on the command-line...
144 */
145
146 filename = argv[6];
147 tempfile[0] = '\0';
148 }
149
150 /*
151 * Load the PPD file and mark options...
152 */
153
154 ppd = ppdOpenFile(getenv("PPD"));
155 num_options = cupsParseOptions(argv[5], 0, &options);
156
157 ppdMarkDefaults(ppd);
158 cupsMarkOptions(ppd, num_options, options);
159
160 /*
161 * Build the command-line for the pdftops or gs filter...
162 */
163
164 #ifdef HAVE_PDFTOPS
165 pdfargv[0] = (char *)"pdftops";
166 pdfargc = 1;
167 #else
168 pdfargv[0] = (char *)"gs";
169 pdfargv[1] = (char *)"-q";
170 pdfargv[2] = (char *)"-dNOPAUSE";
171 pdfargv[3] = (char *)"-dBATCH";
172 pdfargv[4] = (char *)"-dSAFER";
173 pdfargv[5] = (char *)"-sDEVICE=pswrite";
174 pdfargv[6] = (char *)"-sOUTPUTFILE=%stdout";
175 pdfargc = 7;
176 #endif /* HAVE_PDFTOPS */
177
178 if (ppd)
179 {
180 /*
181 * Set language level and TrueType font handling...
182 */
183
184 if (ppd->language_level == 1)
185 {
186 #ifdef HAVE_PDFTOPS
187 pdfargv[pdfargc++] = (char *)"-level1";
188 pdfargv[pdfargc++] = (char *)"-noembtt";
189 #else
190 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=1";
191 #endif /* HAVE_PDFTOPS */
192 }
193 else if (ppd->language_level == 2)
194 {
195 #ifdef HAVE_PDFTOPS
196 pdfargv[pdfargc++] = (char *)"-level2";
197 if (!ppd->ttrasterizer)
198 pdfargv[pdfargc++] = (char *)"-noembtt";
199 #else
200 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=2";
201 #endif /* HAVE_PDFTOPS */
202 }
203 else
204 #ifdef HAVE_PDFTOPS
205 pdfargv[pdfargc++] = (char *)"-level3";
206 #else
207 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=3";
208 #endif /* HAVE_PDFTOPS */
209
210 if ((val = cupsGetOption("fitplot", num_options, options)) == NULL)
211 val = cupsGetOption("fit-to-page", num_options, options);
212
213 if (val && strcasecmp(val, "no") && strcasecmp(val, "off") &&
214 strcasecmp(val, "false"))
215 fit = 1;
216 else
217 fit = 0;
218
219 /*
220 * Set output page size...
221 */
222
223 size = ppdPageSize(ppd, NULL);
224 if (size && fit)
225 {
226 /*
227 * Got the size, now get the orientation...
228 */
229
230 orientation = 0;
231
232 if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
233 {
234 if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 &&
235 strcasecmp(val, "false") != 0)
236 orientation = 1;
237 }
238 else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
239 {
240 /*
241 * Map IPP orientation values to 0 to 3:
242 *
243 * 3 = 0 degrees = 0
244 * 4 = 90 degrees = 1
245 * 5 = -90 degrees = 3
246 * 6 = 180 degrees = 2
247 */
248
249 orientation = atoi(val) - 3;
250 if (orientation >= 2)
251 orientation ^= 1;
252 }
253
254 #ifdef HAVE_PDFTOPS
255 if (orientation & 1)
256 {
257 snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->length);
258 snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->width);
259 }
260 else
261 {
262 snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->width);
263 snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->length);
264 }
265
266 pdfargv[pdfargc++] = (char *)"-paperw";
267 pdfargv[pdfargc++] = pdfwidth;
268 pdfargv[pdfargc++] = (char *)"-paperh";
269 pdfargv[pdfargc++] = pdfheight;
270 pdfargv[pdfargc++] = (char *)"-expand";
271
272 #else
273 if (orientation & 1)
274 {
275 snprintf(pdfwidth, sizeof(pdfwidth), "-dDEVICEWIDTHPOINTS=%.0f",
276 size->length);
277 snprintf(pdfheight, sizeof(pdfheight), "-dDEVICEHEIGHTPOINTS=%.0f",
278 size->width);
279 }
280 else
281 {
282 snprintf(pdfwidth, sizeof(pdfwidth), "-dDEVICEWIDTHPOINTS=%.0f",
283 size->width);
284 snprintf(pdfheight, sizeof(pdfheight), "-dDEVICEHEIGHTPOINTS=%.0f",
285 size->length);
286 }
287
288 pdfargv[pdfargc++] = pdfwidth;
289 pdfargv[pdfargc++] = pdfheight;
290 #endif /* HAVE_PDFTOPS */
291 }
292 }
293
294 #ifdef HAVE_PDFTOPS
295 pdfargv[pdfargc++] = filename;
296 pdfargv[pdfargc++] = (char *)"-";
297 #else
298 pdfargv[pdfargc++] = (char *)"-c";
299 pdfargv[pdfargc++] = (char *)"save pop";
300 pdfargv[pdfargc++] = (char *)"-f";
301 pdfargv[pdfargc++] = filename;
302 #endif /* HAVE_PDFTOPS */
303
304 pdfargv[pdfargc] = NULL;
305
306 if ((pdfpid = fork()) == 0)
307 {
308 /*
309 * Child comes here...
310 */
311
312 #ifdef HAVE_PDFTOPS
313 execv(CUPS_PDFTOPS, pdfargv);
314 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
315 #else
316 execv(CUPS_GHOSTSCRIPT, pdfargv);
317 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
318 #endif /* HAVE_PDFTOPS */
319
320 exit(1);
321 }
322 else if (pdfpid < 0)
323 {
324 /*
325 * Unable to fork!
326 */
327
328 #ifdef HAVE_PDFTOPS
329 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
330 #else
331 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
332 #endif /* HAVE_PDFTOPS */
333
334 pdfstatus = 1;
335 }
336 else
337 {
338 /*
339 * Parent comes here...
340 */
341
342 while ((pdfwaitpid = wait(&pdfstatus)) != pdfpid && errno == EINTR)
343 {
344 /*
345 * Wait until we get a valid process ID or the job is canceled...
346 */
347
348 if (job_canceled)
349 {
350 kill(pdfpid, SIGTERM);
351 job_canceled = 0;
352 }
353 }
354
355 if (pdfstatus)
356 {
357 if (WIFEXITED(pdfstatus))
358 {
359 pdfstatus = WEXITSTATUS(pdfstatus);
360
361 _cupsLangPrintf(stderr,
362 _("ERROR: pdftops filter exited with status %d!\n"),
363 pdfstatus);
364 }
365 else
366 {
367 pdfstatus = WTERMSIG(pdfstatus);
368
369 _cupsLangPrintf(stderr,
370 _("ERROR: pdftops filter crashed on signal %d!\n"),
371 pdfstatus);
372 }
373 }
374 }
375
376 /*
377 * Cleanup and exit...
378 */
379
380 if (tempfile[0])
381 unlink(tempfile);
382
383 return (pdfstatus);
384 }
385
386
387 /*
388 * 'cancel_job()' - Flag the job as canceled.
389 */
390
391 static void
392 cancel_job(int sig) /* I - Signal number (unused) */
393 {
394 (void)sig;
395
396 job_canceled = 1;
397 }
398
399
400 /*
401 * End of "$Id$".
402 */