]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/pdftops.c
Import CUPS 1.4svn-r7226.
[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
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 */