]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/pdftops.c
4 * PDF to PostScript filter front-end for the Common UNIX Printing
7 * Copyright 2007-2009 by Apple Inc.
8 * Copyright 1997-2006 by Easy Software Products.
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/".
18 * main() - Main entry for filter...
19 * cancel_job() - Flag the job as canceled.
23 * Include necessary headers...
26 #include <cups/cups.h>
27 #include <cups/string.h>
28 #include <cups/i18n.h>
38 static void cancel_job(int sig
);
45 static int job_canceled
= 0;
49 * 'main()' - Main entry for filter...
52 int /* O - Exit status */
53 main(int argc
, /* I - Number of command-line args */
54 char *argv
[]) /* I - Command-line arguments */
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 pdf_pid
, /* Process ID for pdftops */
69 pdf_argc
, /* Number of args for pdftops */
70 pstops_pid
, /* Process ID of pstops filter */
71 pstops_pipe
[2], /* Pipe to pstops filter */
72 wait_children
, /* Number of child processes left */
73 wait_pid
, /* Process ID from wait() */
74 wait_status
, /* Status from child */
75 exit_status
= 0; /* Exit status */
76 char *pdf_argv
[100], /* Arguments for pdftops/gs */
77 pdf_width
[255], /* Paper width */
78 pdf_height
[255], /* Paper height */
79 pstops_path
[1024], /* Path to pstops program */
80 *pstops_argv
[7], /* Arguments for pstops filter */
81 *pstops_options
, /* Options for pstops filter */
82 *pstops_start
, /* Start of pstops filter option */
83 *pstops_end
; /* End of pstops filter option */
84 const char *cups_serverbin
; /* CUPS_SERVERBIN environment variable */
85 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
86 struct sigaction action
; /* Actions for POSIX signals */
87 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
91 * Make sure status messages are not buffered...
97 * Make sure we have the right number of arguments for CUPS!
100 if (argc
< 6 || argc
> 7)
102 _cupsLangPrintf(stderr
,
103 _("Usage: %s job user title copies options [filename]\n"),
109 * Register a signal handler to cleanly cancel a job.
112 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
113 sigset(SIGTERM
, cancel_job
);
114 #elif defined(HAVE_SIGACTION)
115 memset(&action
, 0, sizeof(action
));
117 sigemptyset(&action
.sa_mask
);
118 action
.sa_handler
= cancel_job
;
119 sigaction(SIGTERM
, &action
, NULL
);
121 signal(SIGTERM
, cancel_job
);
122 #endif /* HAVE_SIGSET */
125 * Copy stdin if needed...
131 * Copy stdin to a temp file...
134 if ((fd
= cupsTempFd(tempfile
, sizeof(tempfile
))) < 0)
136 _cupsLangPrintError(_("ERROR: Unable to copy PDF file"));
140 fprintf(stderr
, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
143 while ((bytes
= fread(buffer
, 1, sizeof(buffer
), stdin
)) > 0)
144 write(fd
, buffer
, bytes
);
153 * Use the filename on the command-line...
161 * Load the PPD file and mark options...
164 ppd
= ppdOpenFile(getenv("PPD"));
165 num_options
= cupsParseOptions(argv
[5], 0, &options
);
167 ppdMarkDefaults(ppd
);
168 cupsMarkOptions(ppd
, num_options
, options
);
171 * Build the pstops command-line...
174 if ((cups_serverbin
= getenv("CUPS_SERVERBIN")) == NULL
)
175 cups_serverbin
= CUPS_SERVERBIN
;
177 snprintf(pstops_path
, sizeof(pstops_path
), "%s/filter/pstops",
180 pstops_options
= strdup(argv
[5]);
182 if ((pstops_start
= strstr(pstops_options
, "fitplot")) != NULL
&&
183 (!pstops_start
[7] || isspace(pstops_start
[7] & 255)))
186 * Strip [no]fitplot option...
189 pstops_end
= pstops_start
+ 7;
191 if ((pstops_start
- pstops_options
) >= 2 &&
192 !strncmp(pstops_start
- 2, "no", 2))
195 while (*pstops_end
&& isspace(*pstops_end
& 255))
198 _cups_strcpy(pstops_start
, pstops_end
);
201 if ((pstops_start
= strstr(pstops_options
, "fit-to-page")) != NULL
&&
202 (!pstops_start
[11] || isspace(pstops_start
[11] & 255)))
205 * Strip [no]fit-to-page option...
208 pstops_end
= pstops_start
+ 11;
210 if ((pstops_start
- pstops_options
) >= 2 &&
211 !strncmp(pstops_start
- 2, "no", 2))
214 while (*pstops_end
&& isspace(*pstops_end
& 255))
217 _cups_strcpy(pstops_start
, pstops_end
);
220 if ((pstops_start
= strstr(pstops_options
, "landscape")) != NULL
&&
221 (!pstops_start
[9] || isspace(pstops_start
[9] & 255)))
224 * Strip [no]landscape option...
227 pstops_end
= pstops_start
+ 9;
229 if ((pstops_start
- pstops_options
) >= 2 &&
230 !strncmp(pstops_start
- 2, "no", 2))
233 while (*pstops_end
&& isspace(*pstops_end
& 255))
236 _cups_strcpy(pstops_start
, pstops_end
);
239 if ((pstops_start
= strstr(pstops_options
, "orientation-requested=")) != NULL
)
242 * Strip [no]fitplot option...
245 pstops_end
= pstops_start
+ 22;
246 while (*pstops_end
&& !isspace(*pstops_end
& 255))
249 _cups_strcpy(pstops_start
, pstops_end
);
252 pstops_argv
[0] = argv
[0]; /* Printer */
253 pstops_argv
[1] = argv
[1]; /* Job */
254 pstops_argv
[2] = argv
[2]; /* User */
255 pstops_argv
[3] = argv
[3]; /* Title */
256 pstops_argv
[4] = argv
[4]; /* Copies */
257 pstops_argv
[5] = pstops_options
; /* Options */
258 pstops_argv
[6] = NULL
;
261 * Build the command-line for the pdftops or gs filter...
265 pdf_argv
[0] = (char *)"pdftops";
268 pdf_argv
[0] = (char *)"gs";
269 pdf_argv
[1] = (char *)"-q";
270 pdf_argv
[2] = (char *)"-dNOPAUSE";
271 pdf_argv
[3] = (char *)"-dBATCH";
272 pdf_argv
[4] = (char *)"-dSAFER";
273 pdf_argv
[5] = (char *)"-sDEVICE=pswrite";
274 pdf_argv
[6] = (char *)"-sOUTPUTFILE=%stdout";
276 #endif /* HAVE_PDFTOPS */
281 * Set language level and TrueType font handling...
284 if (ppd
->language_level
== 1)
287 pdf_argv
[pdf_argc
++] = (char *)"-level1";
288 pdf_argv
[pdf_argc
++] = (char *)"-noembtt";
290 pdf_argv
[pdf_argc
++] = (char *)"-dLanguageLevel=1";
291 #endif /* HAVE_PDFTOPS */
293 else if (ppd
->language_level
== 2)
296 pdf_argv
[pdf_argc
++] = (char *)"-level2";
297 if (!ppd
->ttrasterizer
)
298 pdf_argv
[pdf_argc
++] = (char *)"-noembtt";
300 pdf_argv
[pdf_argc
++] = (char *)"-dLanguageLevel=2";
301 #endif /* HAVE_PDFTOPS */
305 pdf_argv
[pdf_argc
++] = (char *)"-level3";
307 pdf_argv
[pdf_argc
++] = (char *)"-dLanguageLevel=3";
308 #endif /* HAVE_PDFTOPS */
310 if ((val
= cupsGetOption("fitplot", num_options
, options
)) == NULL
)
311 val
= cupsGetOption("fit-to-page", num_options
, options
);
313 if (val
&& strcasecmp(val
, "no") && strcasecmp(val
, "off") &&
314 strcasecmp(val
, "false"))
320 * Set output page size...
323 size
= ppdPageSize(ppd
, NULL
);
327 * Got the size, now get the orientation...
332 if ((val
= cupsGetOption("landscape", num_options
, options
)) != NULL
)
334 if (strcasecmp(val
, "no") != 0 && strcasecmp(val
, "off") != 0 &&
335 strcasecmp(val
, "false") != 0)
338 else if ((val
= cupsGetOption("orientation-requested", num_options
, options
)) != NULL
)
341 * Map IPP orientation values to 0 to 3:
345 * 5 = -90 degrees = 3
346 * 6 = 180 degrees = 2
349 orientation
= atoi(val
) - 3;
350 if (orientation
>= 2)
357 snprintf(pdf_width
, sizeof(pdf_width
), "%.0f", size
->length
);
358 snprintf(pdf_height
, sizeof(pdf_height
), "%.0f", size
->width
);
362 snprintf(pdf_width
, sizeof(pdf_width
), "%.0f", size
->width
);
363 snprintf(pdf_height
, sizeof(pdf_height
), "%.0f", size
->length
);
366 pdf_argv
[pdf_argc
++] = (char *)"-paperw";
367 pdf_argv
[pdf_argc
++] = pdf_width
;
368 pdf_argv
[pdf_argc
++] = (char *)"-paperh";
369 pdf_argv
[pdf_argc
++] = pdf_height
;
370 pdf_argv
[pdf_argc
++] = (char *)"-expand";
375 snprintf(pdf_width
, sizeof(pdf_width
), "-dDEVICEWIDTHPOINTS=%.0f",
377 snprintf(pdf_height
, sizeof(pdf_height
), "-dDEVICEHEIGHTPOINTS=%.0f",
382 snprintf(pdf_width
, sizeof(pdf_width
), "-dDEVICEWIDTHPOINTS=%.0f",
384 snprintf(pdf_height
, sizeof(pdf_height
), "-dDEVICEHEIGHTPOINTS=%.0f",
388 pdf_argv
[pdf_argc
++] = pdf_width
;
389 pdf_argv
[pdf_argc
++] = pdf_height
;
390 #endif /* HAVE_PDFTOPS */
395 pdf_argv
[pdf_argc
++] = filename
;
396 pdf_argv
[pdf_argc
++] = (char *)"-";
398 pdf_argv
[pdf_argc
++] = (char *)"-c";
399 pdf_argv
[pdf_argc
++] = (char *)"save pop";
400 pdf_argv
[pdf_argc
++] = (char *)"-f";
401 pdf_argv
[pdf_argc
++] = filename
;
402 #endif /* HAVE_PDFTOPS */
404 pdf_argv
[pdf_argc
] = NULL
;
407 * Execute "pdftops/gs | pstops"...
410 if (pipe(pstops_pipe
))
412 _cupsLangPrintError(_("ERROR: Unable to create pipe"));
418 if ((pdf_pid
= fork()) == 0)
421 * Child comes here...
424 dup2(pstops_pipe
[1], 1);
425 close(pstops_pipe
[0]);
426 close(pstops_pipe
[1]);
429 execv(CUPS_PDFTOPS
, pdf_argv
);
430 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
432 execv(CUPS_GHOSTSCRIPT
, pdf_argv
);
433 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
434 #endif /* HAVE_PDFTOPS */
438 else if (pdf_pid
< 0)
445 _cupsLangPrintError(_("ERROR: Unable to execute pdftops program"));
447 _cupsLangPrintError(_("ERROR: Unable to execute gs program"));
448 #endif /* HAVE_PDFTOPS */
454 fprintf(stderr
, "DEBUG: Started filter %s (PID %d)\n", pdf_argv
[0], pdf_pid
);
456 if ((pstops_pid
= fork()) == 0)
459 * Child comes here...
462 dup2(pstops_pipe
[0], 0);
463 close(pstops_pipe
[0]);
464 close(pstops_pipe
[1]);
466 execv(pstops_path
, pstops_argv
);
467 _cupsLangPrintError(_("ERROR: Unable to execute pstops program"));
471 else if (pstops_pid
< 0)
477 _cupsLangPrintError(_("ERROR: Unable to execute pstops program"));
483 fprintf(stderr
, "DEBUG: Started filter pstops (PID %d)\n", pstops_pid
);
485 close(pstops_pipe
[0]);
486 close(pstops_pipe
[1]);
489 * Wait for the child processes to exit...
494 while (wait_children
> 0)
497 * Wait until we get a valid process ID or the job is canceled...
500 while ((wait_pid
= wait(&wait_status
)) < 0 && errno
== EINTR
)
504 kill(pdf_pid
, SIGTERM
);
505 kill(pstops_pid
, SIGTERM
);
517 * Report child status...
522 if (WIFEXITED(wait_status
))
524 exit_status
= WEXITSTATUS(wait_status
);
526 fprintf(stderr
, "DEBUG: PID %d (%s) stopped with status %d!\n",
529 wait_pid
== pdf_pid
? "pdftops" : "pstops",
531 wait_pid
== pdf_pid
? "gs" : "pstops",
532 #endif /* HAVE_PDFTOPS */
535 else if (WTERMSIG(wait_status
) == SIGTERM
)
538 "DEBUG: PID %d (%s) was terminated normally with signal %d!\n",
541 wait_pid
== pdf_pid
? "pdftops" : "pstops",
543 wait_pid
== pdf_pid
? "gs" : "pstops",
544 #endif /* HAVE_PDFTOPS */
549 exit_status
= WTERMSIG(wait_status
);
551 fprintf(stderr
, "DEBUG: PID %d (%s) crashed on signal %d!\n", wait_pid
,
553 wait_pid
== pdf_pid
? "pdftops" : "pstops",
555 wait_pid
== pdf_pid
? "gs" : "pstops",
556 #endif /* HAVE_PDFTOPS */
562 fprintf(stderr
, "DEBUG: PID %d (%s) exited with no errors.\n", wait_pid
,
564 wait_pid
== pdf_pid
? "pdftops" : "pstops");
566 wait_pid
== pdf_pid
? "gs" : "pstops");
567 #endif /* HAVE_PDFTOPS */
572 * Cleanup and exit...
580 return (exit_status
);
585 * 'cancel_job()' - Flag the job as canceled.
589 cancel_job(int sig
) /* I - Signal number (unused) */