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