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