]>
Commit | Line | Data |
---|---|---|
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 | ||
38 | static void cancel_job(int sig); | |
39 | ||
40 | ||
839a51c8 MS |
41 | /* |
42 | * Local globals... | |
43 | */ | |
44 | ||
45 | static int job_canceled = 0; | |
46 | ||
47 | ||
91c84a35 MS |
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 */ | |
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 | ||
324 | static void | |
325 | cancel_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 | */ |