]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/pdftops.c
Import CUPS 1.4svn-r7464.
[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-2008 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 ppd_file_t *ppd; /* PPD file */
66 ppd_size_t *size; /* Current page size */
67 int pdfpid, /* Process ID for pdftops */
68 pdfwaitpid, /* Process ID from wait() */
69 pdfstatus, /* Status from pdftops */
70 pdfargc; /* Number of args for pdftops */
71 char *pdfargv[100], /* Arguments for pdftops/gs */
72 #ifdef HAVE_PDFTOPS
73 pdfwidth[255], /* Paper width */
74 pdfheight[255]; /* Paper height */
75 #else
76 pdfgeometry[255]; /* Paper width and height */
77 #endif /* HAVE_PDFTOPS */
78 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
79 struct sigaction action; /* Actions for POSIX signals */
80 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
81
82
83 /*
84 * Make sure status messages are not buffered...
85 */
86
87 setbuf(stderr, NULL);
88
89 /*
90 * Make sure we have the right number of arguments for CUPS!
91 */
92
93 if (argc < 6 || argc > 7)
94 {
95 _cupsLangPrintf(stderr,
96 _("Usage: %s job user title copies options [filename]\n"),
97 argv[0]);
98 return (1);
99 }
100
101 /*
102 * Register a signal handler to cleanly cancel a job.
103 */
104
105 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
106 sigset(SIGTERM, cancel_job);
107 #elif defined(HAVE_SIGACTION)
108 memset(&action, 0, sizeof(action));
109
110 sigemptyset(&action.sa_mask);
111 action.sa_handler = cancel_job;
112 sigaction(SIGTERM, &action, NULL);
113 #else
114 signal(SIGTERM, cancel_job);
115 #endif /* HAVE_SIGSET */
116
117 /*
118 * Copy stdin if needed...
119 */
120
121 if (argc == 6)
122 {
123 /*
124 * Copy stdin to a temp file...
125 */
126
127 if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
128 {
129 _cupsLangPrintError(_("ERROR: Unable to copy PDF file"));
130 return (1);
131 }
132
133 fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
134 tempfile);
135
136 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
137 write(fd, buffer, bytes);
138
139 close(fd);
140
141 filename = tempfile;
142 }
143 else
144 {
145 /*
146 * Use the filename on the command-line...
147 */
148
149 filename = argv[6];
150 tempfile[0] = '\0';
151 }
152
153 /*
154 * Load the PPD file and mark options...
155 */
156
157 ppd = ppdOpenFile(getenv("PPD"));
158 num_options = cupsParseOptions(argv[5], 0, &options);
159
160 ppdMarkDefaults(ppd);
161 cupsMarkOptions(ppd, num_options, options);
162
163 /*
164 * Build the command-line for the pdftops or gs filter...
165 */
166
167 #ifdef HAVE_PDFTOPS
168 pdfargv[0] = (char *)"pdftops";
169 pdfargc = 1;
170 #else
171 pdfargv[0] = (char *)"gs";
172 pdfargv[1] = (char *)"-q";
173 pdfargv[2] = (char *)"-dNOPAUSE";
174 pdfargv[3] = (char *)"-dBATCH";
175 pdfargv[4] = (char *)"-dSAFER";
176 pdfargv[5] = (char *)"-sDEVICE=pswrite";
177 pdfargv[6] = (char *)"-sOUTPUTFILE=%stdout";
178 pdfargc = 7;
179 #endif /* HAVE_PDFTOPS */
180
181 if (ppd)
182 {
183 /*
184 * Set language level and TrueType font handling...
185 */
186
187 if (ppd->language_level == 1)
188 {
189 #ifdef HAVE_PDFTOPS
190 pdfargv[pdfargc++] = (char *)"-level1";
191 pdfargv[pdfargc++] = (char *)"-noembtt";
192 #else
193 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=1";
194 #endif /* HAVE_PDFTOPS */
195 }
196 else if (ppd->language_level == 2)
197 {
198 #ifdef HAVE_PDFTOPS
199 pdfargv[pdfargc++] = (char *)"-level2";
200 if (!ppd->ttrasterizer)
201 pdfargv[pdfargc++] = (char *)"-noembtt";
202 #else
203 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=2";
204 #endif /* HAVE_PDFTOPS */
205 }
206 else
207 #ifdef HAVE_PDFTOPS
208 pdfargv[pdfargc++] = (char *)"-level3";
209 #else
210 pdfargv[pdfargc++] = (char *)"-dLanguageLevel=3";
211 #endif /* HAVE_PDFTOPS */
212
213 /*
214 * Set output page size...
215 */
216
217 size = ppdPageSize(ppd, NULL);
218 if (size)
219 {
220 /*
221 * Got the size, now get the orientation...
222 */
223
224 orientation = 0;
225
226 if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
227 {
228 if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 &&
229 strcasecmp(val, "false") != 0)
230 orientation = 1;
231 }
232 else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
233 {
234 /*
235 * Map IPP orientation values to 0 to 3:
236 *
237 * 3 = 0 degrees = 0
238 * 4 = 90 degrees = 1
239 * 5 = -90 degrees = 3
240 * 6 = 180 degrees = 2
241 */
242
243 orientation = atoi(val) - 3;
244 if (orientation >= 2)
245 orientation ^= 1;
246 }
247
248 #ifdef HAVE_PDFTOPS
249 if (orientation & 1)
250 {
251 snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->length);
252 snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->width);
253 }
254 else
255 {
256 snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->width);
257 snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->length);
258 }
259
260 pdfargv[pdfargc++] = (char *)"-paperw";
261 pdfargv[pdfargc++] = pdfwidth;
262 pdfargv[pdfargc++] = (char *)"-paperh";
263 pdfargv[pdfargc++] = pdfheight;
264 #else
265 if (orientation & 1)
266 snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->length,
267 size->width);
268 else
269 snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->width,
270 size->length);
271
272 pdfargv[pdfargc++] = pdfgeometry;
273 #endif /* HAVE_PDFTOPS */
274 }
275 }
276
277 #ifdef HAVE_PDFTOPS
278 if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
279 strcasecmp(val, "no") && strcasecmp(val, "off") &&
280 strcasecmp(val, "false"))
281 pdfargv[pdfargc++] = (char *)"-expand";
282
283 pdfargv[pdfargc++] = filename;
284 pdfargv[pdfargc++] = (char *)"-";
285 #else
286 pdfargv[pdfargc++] = (char *)"-c";
287 pdfargv[pdfargc++] = (char *)"save pop";
288 pdfargv[pdfargc++] = (char *)"-f";
289 pdfargv[pdfargc++] = filename;
290 #endif /* HAVE_PDFTOPS */
291
292 pdfargv[pdfargc] = NULL;
293
294 if ((pdfpid = fork()) == 0)
295 {
296 /*
297 * Child comes here...
298 */
299
300 #ifdef HAVE_PDFTOPS
301 execv(CUPS_PDFTOPS, pdfargv);
302 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
303 #else
304 execv(CUPS_GHOSTSCRIPT, pdfargv);
305 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
306 #endif /* HAVE_PDFTOPS */
307
308 exit(1);
309 }
310 else if (pdfpid < 0)
311 {
312 /*
313 * Unable to fork!
314 */
315
316 #ifdef HAVE_PDFTOPS
317 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
318 #else
319 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
320 #endif /* HAVE_PDFTOPS */
321
322 pdfstatus = 1;
323 }
324 else
325 {
326 /*
327 * Parent comes here...
328 */
329
330 while ((pdfwaitpid = wait(&pdfstatus)) < 0 && errno == EINTR)
331 {
332 /*
333 * Wait until we get a valid process ID or the job is canceled...
334 */
335
336 if (job_canceled)
337 break;
338 }
339
340 if (pdfwaitpid != pdfpid)
341 {
342 kill(pdfpid, SIGTERM);
343 pdfstatus = 1;
344 }
345 else if (pdfstatus)
346 {
347 if (WIFEXITED(pdfstatus))
348 {
349 pdfstatus = WEXITSTATUS(pdfstatus);
350
351 _cupsLangPrintf(stderr,
352 _("ERROR: pdftops filter exited with status %d!\n"),
353 pdfstatus);
354 }
355 else
356 {
357 pdfstatus = WTERMSIG(pdfstatus);
358
359 _cupsLangPrintf(stderr,
360 _("ERROR: pdftops filter crashed on signal %d!\n"),
361 pdfstatus);
362 }
363 }
364 }
365
366 /*
367 * Cleanup and exit...
368 */
369
370 if (tempfile[0])
371 unlink(tempfile);
372
373 return (pdfstatus);
374 }
375
376
377 /*
378 * 'cancel_job()' - Flag the job as canceled.
379 */
380
381 static void
382 cancel_job(int sig) /* I - Signal number (unused) */
383 {
384 (void)sig;
385
386 job_canceled = 1;
387 }
388
389
390 /*
391 * End of "$Id$".
392 */