]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/cupsfilter.c
Import CUPS v2.0.2
[thirdparty/cups.git] / scheduler / cupsfilter.c
CommitLineData
bc44d920 1/*
4ef75dec 2 * "$Id: cupsfilter.c 12303 2014-12-09 16:16:07Z msweet $"
bc44d920 3 *
71f63681 4 * Filtering program for CUPS.
bc44d920 5 *
71f63681
MS
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
bc44d920 8 *
71f63681
MS
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
bc44d920 14 */
15
16/*
17 * Include necessary headers...
18 */
19
71e16022 20#include <cups/cups-private.h>
eac3a0a0
MS
21#include <cups/file-private.h>
22#include <cups/ppd-private.h>
bc44d920 23#include "mime.h"
2e4ff8af 24#include <limits.h>
bc44d920 25#include <unistd.h>
26#include <fcntl.h>
2e4ff8af 27#include <signal.h>
bc44d920 28#include <sys/wait.h>
29#if defined(__APPLE__)
30# include <libgen.h>
88f9aafc 31#endif /* __APPLE__ */
bc44d920 32
33
34/*
35 * Local globals...
36 */
37
38static char *DataDir = NULL;/* CUPS_DATADIR environment variable */
39static char *FontPath = NULL;
40 /* CUPS_FONTPATH environment variable */
41static mime_filter_t GZIPFilter = /* gziptoany filter */
42{
43 NULL, /* Source type */
44 NULL, /* Destination type */
45 0, /* Cost */
46 "gziptoany" /* Filter program to run */
47};
48static char *Path = NULL; /* PATH environment variable */
49static char *ServerBin = NULL;
50 /* CUPS_SERVERBIN environment variable */
51static char *ServerRoot = NULL;
52 /* CUPS_SERVERROOT environment variable */
53static char *RIPCache = NULL;
71e16022 54 /* RIP_MAX_CACHE environment variable */
2e4ff8af
MS
55static char TempFile[1024] = "";
56 /* Temporary file */
bc44d920 57
58
59/*
60 * Local functions...
61 */
62
b19ccc9e
MS
63static void add_printer_filter(const char *command, mime_t *mime,
64 mime_type_t *printer_type,
65 const char *filter);
66static mime_type_t *add_printer_filters(const char *command,
67 mime_t *mime, const char *printer,
68 const char *ppdfile,
69 mime_type_t **prefilter_type);
eac3a0a0
MS
70static void check_cb(void *context, _cups_fc_result_t result,
71 const char *message);
b19ccc9e
MS
72static int compare_pids(mime_filter_t *a, mime_filter_t *b);
73static char *escape_options(int num_options, cups_option_t *options);
74static int exec_filter(const char *filter, char **argv,
75 char **envp, int infd, int outfd);
1340db2d
MS
76static int exec_filters(mime_type_t *srctype,
77 cups_array_t *filters, const char *infile,
b19ccc9e
MS
78 const char *outfile, const char *ppdfile,
79 const char *printer, const char *user,
80 const char *title, int num_options,
81 cups_option_t *options);
82static void get_job_file(const char *job);
83static int open_pipe(int *fds);
71f63681 84static int read_cups_files_conf(const char *filename);
b19ccc9e
MS
85static void set_string(char **s, const char *val);
86static void sighandler(int sig);
f3c17241 87static void usage(const char *opt) __attribute__((noreturn));
bc44d920 88
89
90/*
91 * 'main()' - Main entry for the test program.
92 */
93
94int /* O - Exit status */
95main(int argc, /* I - Number of command-line args */
96 char *argv[]) /* I - Command-line arguments */
97{
1a18c85c
MS
98 int i, /* Looping vars */
99 list_filters = 0; /* Just list the filters? */
cc0d019f 100 const char *command, /* Command name */
b19ccc9e
MS
101 *opt, /* Current option */
102 *printer; /* Printer name */
103 mime_type_t *printer_type, /* Printer MIME type */
104 *prefilter_type; /* Printer prefilter MIME type */
cc0d019f
MS
105 char *srctype, /* Source type */
106 *dsttype, /* Destination type */
107 super[MIME_MAX_SUPER], /* Super-type name */
bc44d920 108 type[MIME_MAX_TYPE]; /* Type name */
109 int compression; /* Compression of file */
110 int cost; /* Cost of filters */
111 mime_t *mime; /* MIME database */
dd1abb6b 112 char mimedir[1024]; /* MIME directory */
cc0d019f
MS
113 char *infile, /* File to filter */
114 *outfile; /* File to create */
71f63681 115 char cupsfilesconf[1024]; /* cups-files.conf file */
bc44d920 116 const char *server_root; /* CUPS_SERVERROOT environment variable */
117 mime_type_t *src, /* Source type */
118 *dst; /* Destination type */
119 cups_array_t *filters; /* Filters for the file */
120 int num_options; /* Number of options */
121 cups_option_t *options; /* Options */
122 const char *ppdfile; /* PPD file */
cc0d019f
MS
123 const char *title, /* Title string */
124 *user; /* Username */
1340db2d
MS
125 int all_filters, /* Use all filters */
126 removeppd, /* Remove PPD file */
cc0d019f
MS
127 removeinfile; /* Remove input file */
128 int status; /* Execution status */
bc44d920 129
130
131 /*
132 * Setup defaults...
133 */
134
cc0d019f
MS
135 if ((command = strrchr(argv[0], '/')) != NULL)
136 command ++;
137 else
138 command = argv[0];
139
b19ccc9e 140 printer = !strcmp(command, "convert") ? "tofile" : "cupsfilter";
cc0d019f
MS
141 mime = NULL;
142 srctype = NULL;
91c84a35 143 compression = 0;
cc0d019f
MS
144 dsttype = "application/pdf";
145 infile = NULL;
146 outfile = NULL;
147 num_options = 0;
148 options = NULL;
149 ppdfile = NULL;
150 title = NULL;
151 user = cupsUser();
1340db2d 152 all_filters = 0;
cc0d019f
MS
153 removeppd = 0;
154 removeinfile = 0;
bc44d920 155
156 if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
157 server_root = CUPS_SERVERROOT;
158
71f63681 159 snprintf(cupsfilesconf, sizeof(cupsfilesconf), "%s/cups-files.conf", server_root);
bc44d920 160
161 /*
162 * Process command-line arguments...
163 */
164
165 _cupsSetLocale(argv);
166
167 for (i = 1; i < argc; i ++)
1a18c85c 168 {
bc44d920 169 if (argv[i][0] == '-')
170 {
1a18c85c
MS
171 if (!strcmp(argv[i], "--list-filters"))
172 {
173 list_filters = 1;
174 }
175 else if (!strcmp(argv[i], "--"))
176 {
177 i ++;
178 if (i < argc && !infile)
179 infile = argv[i];
180 else
4ef75dec 181 usage(NULL);
1a18c85c
MS
182 }
183 else
184 {
185 for (opt = argv[i] + 1; *opt; opt ++)
bc44d920 186 {
1a18c85c
MS
187 switch (*opt)
188 {
189 case 'a' : /* Specify option... */
190 i ++;
191 if (i < argc)
192 num_options = cupsParseOptions(argv[i], num_options, &options);
cc0d019f 193 else
f3c17241 194 usage(opt);
1a18c85c 195 break;
cc0d019f 196
1a18c85c
MS
197 case 'c' : /* Specify cups-files.conf file location... */
198 i ++;
199 if (i < argc)
200 {
201 if (!strcmp(command, "convert"))
202 num_options = cupsAddOption("copies", argv[i], num_options, &options);
203 else
204 strlcpy(cupsfilesconf, argv[i], sizeof(cupsfilesconf));
205 }
206 else
207 usage(opt);
208 break;
bc44d920 209
1a18c85c
MS
210 case 'd' : /* Specify the real printer name */
211 i ++;
212 if (i < argc)
213 printer = argv[i];
214 else
215 usage(opt);
216 break;
217
218 case 'D' : /* Delete input file after conversion */
219 removeinfile = 1;
220 break;
221
222 case 'e' : /* Use every filter from the PPD file */
223 all_filters = 1;
224 break;
225
226 case 'f' : /* Specify input file... */
227 i ++;
228 if (i < argc && !infile)
229 infile = argv[i];
230 else
231 usage(opt);
232 break;
233
234 case 'i' : /* Specify source MIME type... */
235 i ++;
2e4ff8af
MS
236 if (i < argc)
237 {
1a18c85c
MS
238 if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
239 usage(opt);
240
241 srctype = argv[i];
2e4ff8af
MS
242 }
243 else
f3c17241 244 usage(opt);
1a18c85c
MS
245 break;
246
247 case 'j' : /* Get job file or specify destination MIME type... */
248 if (strcmp(command, "convert"))
249 {
250 i ++;
251 if (i < argc)
252 {
253 get_job_file(argv[i]);
254 infile = TempFile;
255 }
256 else
257 usage(opt);
2e4ff8af 258
1a18c85c
MS
259 break;
260 }
2e4ff8af 261
1a18c85c
MS
262 case 'm' : /* Specify destination MIME type... */
263 i ++;
264 if (i < argc)
265 {
266 if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
267 usage(opt);
268
269 dsttype = argv[i];
270 }
271 else
f3c17241 272 usage(opt);
1a18c85c 273 break;
cc0d019f 274
1a18c85c
MS
275 case 'n' : /* Specify number of copies... */
276 i ++;
277 if (i < argc)
278 num_options = cupsAddOption("copies", argv[i], num_options, &options);
279 else
280 usage(opt);
281 break;
282
283 case 'o' : /* Specify option(s) or output filename */
284 i ++;
285 if (i < argc)
cc0d019f 286 {
1a18c85c
MS
287 if (!strcmp(command, "convert"))
288 {
289 if (outfile)
290 usage(NULL);
291 else
292 outfile = argv[i];
293 }
cc0d019f 294 else
1a18c85c 295 num_options = cupsParseOptions(argv[i], num_options, &options);
cc0d019f
MS
296 }
297 else
1a18c85c
MS
298 usage(opt);
299 break;
300
301 case 'p' : /* Specify PPD file... */
302 case 'P' : /* Specify PPD file... */
303 i ++;
304 if (i < argc)
305 ppdfile = argv[i];
306 else
307 usage(opt);
308 break;
309
310 case 't' : /* Specify title... */
311 case 'J' : /* Specify title... */
312 i ++;
313 if (i < argc)
314 title = argv[i];
315 else
316 usage(opt);
317 break;
318
319 case 'u' : /* Delete PPD file after conversion */
320 removeppd = 1;
321 break;
322
323 case 'U' : /* Specify username... */
324 i ++;
325 if (i < argc)
326 user = argv[i];
327 else
328 usage(opt);
329 break;
330
331 default : /* Something we don't understand... */
332 usage(opt);
333 break;
334 }
bc44d920 335 }
1a18c85c 336 }
bc44d920 337 }
cc0d019f
MS
338 else if (!infile)
339 {
340 if (strcmp(command, "convert"))
341 infile = argv[i];
342 else
f3c17241 343 usage(NULL);
cc0d019f 344 }
bc44d920 345 else
346 {
347 _cupsLangPuts(stderr,
0837b7e8 348 _("cupsfilter: Only one filename can be specified."));
f3c17241 349 usage(NULL);
bc44d920 350 }
1a18c85c 351 }
bc44d920 352
cc0d019f 353 if (!infile && !srctype)
f3c17241 354 usage(NULL);
bc44d920 355
356 if (!title)
357 {
cc0d019f
MS
358 if (!infile)
359 title = "(stdin)";
360 else if ((title = strrchr(infile, '/')) != NULL)
bc44d920 361 title ++;
362 else
cc0d019f 363 title = infile;
bc44d920 364 }
365
366 /*
71f63681 367 * Load the cups-files.conf file and create the MIME database...
bc44d920 368 */
369
71f63681 370 if (read_cups_files_conf(cupsfilesconf))
bc44d920 371 return (1);
372
75bd9771
MS
373 snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
374
375 mime = mimeLoadTypes(NULL, mimedir);
376 mime = mimeLoadTypes(mime, ServerRoot);
377 mime = mimeLoadFilters(mime, mimedir, Path);
378 mime = mimeLoadFilters(mime, ServerRoot, Path);
379
380 if (!mime)
bc44d920 381 {
382 _cupsLangPrintf(stderr,
75bd9771 383 _("%s: Unable to read MIME database from \"%s\" or "
0837b7e8 384 "\"%s\"."),
75bd9771 385 command, mimedir, ServerRoot);
bc44d920 386 return (1);
387 }
388
f228370c
MS
389 prefilter_type = NULL;
390
1340db2d 391 if (all_filters)
1340db2d
MS
392 printer_type = add_printer_filters(command, mime, printer, ppdfile,
393 &prefilter_type);
1340db2d 394 else
1340db2d 395 printer_type = mimeType(mime, "application", "vnd.cups-postscript");
b19ccc9e 396
bc44d920 397 /*
398 * Get the source and destination types...
399 */
400
cc0d019f
MS
401 if (srctype)
402 {
0fa6c7fa 403 /* sscanf return value already checked above */
cc0d019f
MS
404 sscanf(srctype, "%15[^/]/%255s", super, type);
405 if ((src = mimeType(mime, super, type)) == NULL)
406 {
407 _cupsLangPrintf(stderr,
0837b7e8 408 _("%s: Unknown source MIME type %s/%s."),
cc0d019f
MS
409 command, super, type);
410 return (1);
411 }
412 }
413 else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL)
bc44d920 414 {
415 _cupsLangPrintf(stderr,
0837b7e8 416 _("%s: Unable to determine MIME type of \"%s\"."),
cc0d019f 417 command, infile);
bc44d920 418 return (1);
419 }
420
0fa6c7fa 421 /* sscanf return value already checked above */
cc0d019f 422 sscanf(dsttype, "%15[^/]/%255s", super, type);
88f9aafc 423 if (!_cups_strcasecmp(super, "printer"))
b19ccc9e
MS
424 dst = printer_type;
425 else if ((dst = mimeType(mime, super, type)) == NULL)
bc44d920 426 {
427 _cupsLangPrintf(stderr,
0837b7e8 428 _("%s: Unknown destination MIME type %s/%s."),
cc0d019f 429 command, super, type);
bc44d920 430 return (1);
431 }
432
433 /*
434 * Figure out how to filter the file...
435 */
436
437 if (src == dst)
438 {
439 /*
440 * Special case - no filtering needed...
441 */
442
443 filters = cupsArrayNew(NULL, NULL);
444 cupsArrayAdd(filters, &GZIPFilter);
1340db2d
MS
445 GZIPFilter.src = src;
446 GZIPFilter.dst = dst;
bc44d920 447 }
448 else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
449 {
450 _cupsLangPrintf(stderr,
0837b7e8 451 _("%s: No filter to convert from %s/%s to %s/%s."),
cc0d019f 452 command, src->super, src->type, dst->super, dst->type);
bc44d920 453 return (1);
454 }
455 else if (compression)
456 cupsArrayInsert(filters, &GZIPFilter);
457
b19ccc9e
MS
458 if (prefilter_type)
459 {
460 /*
461 * Add pre-filters...
462 */
463
464 mime_filter_t *filter, /* Current filter */
465 *prefilter; /* Current pre-filter */
466 cups_array_t *prefilters = cupsArrayNew(NULL, NULL);
467 /* New filters array */
468
469
470 for (filter = (mime_filter_t *)cupsArrayFirst(filters);
471 filter;
472 filter = (mime_filter_t *)cupsArrayNext(filters))
473 {
1340db2d
MS
474 if ((prefilter = mimeFilterLookup(mime, filter->src,
475 prefilter_type)) != NULL)
b19ccc9e
MS
476 cupsArrayAdd(prefilters, prefilter);
477
478 cupsArrayAdd(prefilters, filter);
479 }
480
481 cupsArrayDelete(filters);
482 filters = prefilters;
483 }
484
1a18c85c
MS
485 if (list_filters)
486 {
487 /*
488 * List filters...
489 */
490
491 mime_filter_t *filter; /* Current filter */
492
493 for (filter = (mime_filter_t *)cupsArrayFirst(filters);
494 filter;
495 filter = (mime_filter_t *)cupsArrayNext(filters))
496 if (strcmp(filter->filter, "-"))
497 _cupsLangPuts(stdout, filter->filter);
bc44d920 498
1a18c85c
MS
499 status = 0;
500 }
501 else
502 {
503 /*
504 * Run filters...
505 */
506
507 status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user,
508 title, num_options, options);
509 }
cc0d019f
MS
510
511 /*
512 * Remove files as needed, then exit...
513 */
514
2e4ff8af
MS
515 if (TempFile[0])
516 unlink(TempFile);
517
cc0d019f
MS
518 if (removeppd && ppdfile)
519 unlink(ppdfile);
520
521 if (removeinfile && infile)
522 unlink(infile);
523
524 return (status);
bc44d920 525}
526
527
b19ccc9e
MS
528/*
529 * 'add_printer_filter()' - Add a single filters from a PPD file.
530 */
531
532static void
533add_printer_filter(
534 const char *command, /* I - Command name */
535 mime_t *mime, /* I - MIME database */
536 mime_type_t *filtertype, /* I - Printer or prefilter MIME type */
537 const char *filter) /* I - Filter to add */
538{
539 char super[MIME_MAX_SUPER], /* Super-type for filter */
540 type[MIME_MAX_TYPE], /* Type for filter */
eac3a0a0
MS
541 dsuper[MIME_MAX_SUPER], /* Destination super-type for filter */
542 dtype[MIME_MAX_TYPE], /* Destination type for filter */
543 dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
544 /* Destination super/type */
b19ccc9e
MS
545 program[1024]; /* Program/filter name */
546 int cost; /* Cost of filter */
eac3a0a0
MS
547 size_t maxsize = 0; /* Maximum supported file size */
548 mime_type_t *temptype, /* MIME type looping var */
549 *desttype; /* Destination MIME type */
550 mime_filter_t *filterptr; /* MIME filter */
b19ccc9e
MS
551
552
553 /*
eac3a0a0 554 * Parse the filter string; it should be in one of the following formats:
b19ccc9e 555 *
eac3a0a0
MS
556 * source/type cost program
557 * source/type cost maxsize(nnnn) program
558 * source/type dest/type cost program
559 * source/type dest/type cost maxsize(nnnn) program
b19ccc9e
MS
560 */
561
eac3a0a0
MS
562 if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
563 super, type, dsuper, dtype, &cost, program) == 6)
b19ccc9e 564 {
eac3a0a0
MS
565 snprintf(dest, sizeof(dest), "%s/%s/%s", filtertype->type, dsuper, dtype);
566
567 if ((desttype = mimeType(mime, "printer", dest)) == NULL)
568 desttype = mimeAddType(mime, "printer", dest);
569 }
570 else
571 {
572 if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
573 program) == 4)
574 {
575 desttype = filtertype;
576 }
577 else
578 {
579 _cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"."), command,
580 filter);
581 return;
582 }
583 }
584
585 if (!strncmp(program, "maxsize(", 8))
586 {
587 char *ptr; /* Pointer into maxsize(nnnn) program */
588
1a18c85c 589 maxsize = (size_t)strtoll(program + 8, &ptr, 10);
eac3a0a0
MS
590
591 if (*ptr != ')')
592 {
593 printf("testmime: Invalid filter string \"%s\".\n", filter);
594 return;
595 }
596
597 ptr ++;
598 while (_cups_isspace(*ptr))
599 ptr ++;
600
601 _cups_strcpy(program, ptr);
b19ccc9e
MS
602 }
603
604 /*
605 * See if the filter program exists; if not, stop the printer and flag
606 * the error!
607 */
608
609 if (strcmp(program, "-"))
610 {
eac3a0a0
MS
611 char filename[1024]; /* Full path to program */
612
b19ccc9e
MS
613 if (program[0] == '/')
614 strlcpy(filename, program, sizeof(filename));
615 else
616 snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
617
eac3a0a0
MS
618 if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !geteuid(), check_cb,
619 (void *)command))
b19ccc9e 620 return;
b19ccc9e
MS
621 }
622
623 /*
624 * Add the filter to the MIME database, supporting wildcards as needed...
625 */
626
627 for (temptype = mimeFirstType(mime);
628 temptype;
629 temptype = mimeNextType(mime))
88f9aafc
MS
630 if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
631 !_cups_strcasecmp(temptype->super, super)) &&
632 (type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
eac3a0a0
MS
633 {
634 if (desttype != filtertype)
635 {
636 filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);
637
638 if (!mimeFilterLookup(mime, desttype, filtertype))
771bd8cb 639 mimeAddFilter(mime, desttype, filtertype, 0, "-");
eac3a0a0
MS
640 }
641 else
642 filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);
643
644 if (filterptr)
645 filterptr->maxsize = maxsize;
646 }
b19ccc9e
MS
647}
648
649
650/*
651 * 'add_printer_filters()' - Add filters from a PPD file.
652 */
653
654static mime_type_t * /* O - Printer type or NULL on error */
655add_printer_filters(
656 const char *command, /* I - Command name */
657 mime_t *mime, /* I - MIME database */
658 const char *printer, /* I - Printer name */
659 const char *ppdfile, /* I - PPD file */
660 mime_type_t **prefilter_type) /* O - Prefilter type */
661{
eac3a0a0
MS
662 ppd_file_t *ppd; /* PPD file data */
663 _ppd_cache_t *pc; /* Cache data for PPD */
664 const char *value; /* Filter definition value */
665 mime_type_t *printer_type; /* Printer filter type */
b19ccc9e
MS
666
667
9c80ffa2 668 if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_NONE)) == NULL)
b19ccc9e 669 {
eac3a0a0
MS
670 ppd_status_t status; /* PPD load status */
671 int linenum; /* Line number */
b19ccc9e 672
eac3a0a0 673 status = ppdLastError(&linenum);
0837b7e8 674 _cupsLangPrintf(stderr, _("%s: Unable to open PPD file: %s on line %d."),
eac3a0a0 675 command, ppdErrorString(status), linenum);
b19ccc9e
MS
676 return (NULL);
677 }
678
eac3a0a0
MS
679 pc = _ppdCacheCreateWithPPD(ppd);
680 if (!pc)
681 return (NULL);
682
683 printer_type = mimeAddType(mime, "printer", printer);
684 *prefilter_type = NULL;
b19ccc9e 685
eac3a0a0 686 if (pc->filters)
b19ccc9e 687 {
eac3a0a0
MS
688 for (value = (const char *)cupsArrayFirst(pc->filters);
689 value;
690 value = (const char *)cupsArrayNext(pc->filters))
691 add_printer_filter(command, mime, printer_type, value);
b19ccc9e
MS
692 }
693 else
694 {
695 add_printer_filter(command, mime, printer_type,
eac3a0a0 696 "application/vnd.cups-raw 0 -");
b19ccc9e
MS
697 add_printer_filter(command, mime, printer_type,
698 "application/vnd.cups-postscript 0 -");
699 }
700
eac3a0a0 701 if (pc->prefilters)
b19ccc9e
MS
702 {
703 *prefilter_type = mimeAddType(mime, "prefilter", printer);
704
eac3a0a0
MS
705 for (value = (const char *)cupsArrayFirst(pc->prefilters);
706 value;
707 value = (const char *)cupsArrayNext(pc->prefilters))
708 add_printer_filter(command, mime, *prefilter_type, value);
b19ccc9e 709 }
b19ccc9e
MS
710
711 return (printer_type);
712}
713
714
eac3a0a0
MS
715/*
716 * 'check_cb()' - Callback function for _cupsFileCheck.
717 */
718
719static void
720check_cb(void *context, /* I - Context (command name) */
721 _cups_fc_result_t result, /* I - Result of check */
722 const char *message) /* I - Localized message */
723{
321d8d57
MS
724 (void)result;
725
eac3a0a0
MS
726 _cupsLangPrintf(stderr, _("%s: %s"), (char *)context, message);
727}
728
729
bc44d920 730/*
731 * 'compare_pids()' - Compare two filter PIDs...
732 */
733
734static int /* O - Result of comparison */
735compare_pids(mime_filter_t *a, /* I - First filter */
736 mime_filter_t *b) /* I - Second filter */
737{
738 /*
739 * Because we're particularly lazy, we store the process ID in the "cost"
740 * variable...
741 */
742
743 return (a->cost - b->cost);
744}
745
746
747/*
748 * 'escape_options()' - Convert an options array to a string.
749 */
750
751static char * /* O - Option string */
752escape_options(
753 int num_options, /* I - Number of options */
754 cups_option_t *options) /* I - Options */
755{
756 int i; /* Looping var */
757 cups_option_t *option; /* Current option */
1a18c85c 758 size_t bytes; /* Number of bytes needed */
bc44d920 759 char *s, /* Option string */
760 *sptr, /* Pointer into string */
761 *vptr; /* Pointer into value */
762
763
764 /*
765 * Figure out the worst-case number of bytes we need for the option string.
766 */
767
768 for (i = num_options, option = options, bytes = 1; i > 0; i --, option ++)
769 bytes += 2 * (strlen(option->name) + strlen(option->value)) + 2;
770
91c84a35
MS
771 if ((s = malloc(bytes)) == NULL)
772 return (NULL);
bc44d920 773
774 /*
775 * Copy the options to the string...
776 */
777
778 for (i = num_options, option = options, sptr = s; i > 0; i --, option ++)
779 {
780 if (!strcmp(option->name, "copies"))
781 continue;
782
783 if (sptr > s)
784 *sptr++ = ' ';
785
1a18c85c 786 strlcpy(sptr, option->name, bytes - (size_t)(sptr - s));
bc44d920 787 sptr += strlen(sptr);
788 *sptr++ = '=';
789
790 for (vptr = option->value; *vptr;)
791 {
792 if (strchr("\\ \t\n", *vptr))
793 *sptr++ = '\\';
794
795 *sptr++ = *vptr++;
796 }
797 }
798
799 *sptr = '\0';
800
bc44d920 801 return (s);
802}
803
804
805/*
806 * 'exec_filter()' - Execute a single filter.
807 */
808
809static int /* O - Process ID or -1 on error */
810exec_filter(const char *filter, /* I - Filter to execute */
811 char **argv, /* I - Argument list */
812 char **envp, /* I - Environment list */
813 int infd, /* I - Stdin file descriptor */
814 int outfd) /* I - Stdout file descriptor */
815{
97c9a8d7
MS
816 int pid, /* Process ID */
817 fd; /* Temporary file descriptor */
bc44d920 818#if defined(__APPLE__)
819 char processPath[1024], /* CFProcessPath environment variable */
820 linkpath[1024]; /* Link path for symlinks... */
821 int linkbytes; /* Bytes for link path */
822
823
824 /*
88f9aafc 825 * Add special voodoo magic for MacOS X - this allows MacOS X
bc44d920 826 * programs to access their bundle resources properly...
827 */
828
829 if ((linkbytes = readlink(filter, linkpath, sizeof(linkpath) - 1)) > 0)
830 {
831 /*
832 * Yes, this is a symlink to the actual program, nul-terminate and
833 * use it...
834 */
835
836 linkpath[linkbytes] = '\0';
837
838 if (linkpath[0] == '/')
839 snprintf(processPath, sizeof(processPath), "CFProcessPath=%s",
840 linkpath);
841 else
842 snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
843 dirname((char *)filter), linkpath);
844 }
845 else
846 snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", filter);
847
848 envp[0] = processPath; /* Replace <CFProcessPath> string */
849#endif /* __APPLE__ */
850
851 if ((pid = fork()) == 0)
852 {
853 /*
854 * Child process goes here...
855 *
856 * Update stdin/stdout/stderr as needed...
857 */
858
859 if (infd != 0)
860 {
97c9a8d7
MS
861 if (infd < 0)
862 infd = open("/dev/null", O_RDONLY);
863
bc44d920 864 if (infd > 0)
97c9a8d7
MS
865 {
866 dup2(infd, 0);
867 close(infd);
868 }
bc44d920 869 }
870
871 if (outfd != 1)
872 {
97c9a8d7
MS
873 if (outfd < 0)
874 outfd = open("/dev/null", O_WRONLY);
875
876 if (outfd > 1)
877 {
878 dup2(outfd, 1);
879 close(outfd);
880 }
bc44d920 881 }
882
97c9a8d7
MS
883 if ((fd = open("/dev/null", O_RDWR)) > 3)
884 {
885 dup2(fd, 3);
886 close(fd);
887 }
bc44d920 888 fcntl(3, F_SETFL, O_NDELAY);
889
97c9a8d7
MS
890 if ((fd = open("/dev/null", O_RDWR)) > 4)
891 {
892 dup2(fd, 4);
893 close(fd);
894 }
bc44d920 895 fcntl(4, F_SETFL, O_NDELAY);
896
897 /*
898 * Execute command...
899 */
900
901 execve(filter, argv, envp);
902
903 perror(filter);
904
905 exit(errno);
906 }
907
908 return (pid);
909}
910
911
912/*
913 * 'exec_filters()' - Execute filters for the given file and options.
914 */
915
916static int /* O - 0 on success, 1 on error */
1340db2d
MS
917exec_filters(mime_type_t *srctype, /* I - Source type */
918 cups_array_t *filters, /* I - Array of filters to run */
cc0d019f
MS
919 const char *infile, /* I - File to filter */
920 const char *outfile, /* I - File to create */
bc44d920 921 const char *ppdfile, /* I - PPD file, if any */
db1f069b 922 const char *printer, /* I - Printer name */
cc0d019f 923 const char *user, /* I - Username */
bc44d920 924 const char *title, /* I - Job title */
925 int num_options, /* I - Number of filter options */
926 cups_option_t *options) /* I - Filter options */
927{
cc0d019f 928 int i; /* Looping var */
bc44d920 929 const char *argv[8], /* Command-line arguments */
6961465f 930 *envp[17], /* Environment variables */
bc44d920 931 *temp; /* Temporary string */
932 char *optstr, /* Filter options */
e6013cfa 933 content_type[1024], /* CONTENT_TYPE */
bc44d920 934 cups_datadir[1024], /* CUPS_DATADIR */
935 cups_fontpath[1024], /* CUPS_FONTPATH */
936 cups_serverbin[1024], /* CUPS_SERVERBIN */
937 cups_serverroot[1024], /* CUPS_SERVERROOT */
6961465f
MS
938 final_content_type[1024] = "",
939 /* FINAL_CONTENT_TYPE */
bc44d920 940 lang[1024], /* LANG */
941 path[1024], /* PATH */
942 ppd[1024], /* PPD */
5a6b583a
MS
943 printer_info[255], /* PRINTER_INFO env variable */
944 printer_location[255], /* PRINTER_LOCATION env variable */
945 printer_name[255], /* PRINTER env variable */
71e16022 946 rip_max_cache[1024], /* RIP_MAX_CACHE */
cc0d019f 947 userenv[1024], /* USER */
bc44d920 948 program[1024]; /* Program to run */
949 mime_filter_t *filter, /* Current filter */
950 *next; /* Next filter */
951 int current, /* Current filter */
952 filterfds[2][2], /* Pipes for filters */
953 pid, /* Process ID of filter */
954 status, /* Exit status */
955 retval; /* Return value */
956 cups_array_t *pids; /* Executed filters array */
957 mime_filter_t key; /* Search key for filters */
cc0d019f 958 cups_lang_t *language; /* Current language */
5a6b583a 959 cups_dest_t *dest; /* Destination information */
bc44d920 960
961
6961465f
MS
962 /*
963 * Figure out the final content type...
964 */
965
966 for (filter = (mime_filter_t *)cupsArrayLast(filters);
967 filter && filter->dst;
968 filter = (mime_filter_t *)cupsArrayPrev(filters))
969 if (strcmp(filter->dst->super, "printer"))
970 break;
971
972 if (filter && filter->dst)
973 {
974 const char *ptr; /* Pointer in type name */
975
976 if ((ptr = strchr(filter->dst->type, '/')) != NULL)
977 snprintf(final_content_type, sizeof(final_content_type),
978 "FINAL_CONTENT_TYPE=%s", ptr + 1);
979 else
980 snprintf(final_content_type, sizeof(final_content_type),
981 "FINAL_CONTENT_TYPE=%s/%s", filter->dst->super,
982 filter->dst->type);
983 }
984
985 /*
986 * Remove NULL ("-") filters...
987 */
988
989 for (filter = (mime_filter_t *)cupsArrayFirst(filters);
990 filter;
991 filter = (mime_filter_t *)cupsArrayNext(filters))
992 if (!strcmp(filter->filter, "-"))
993 cupsArrayRemove(filters, filter);
994
bc44d920 995 /*
996 * Setup the filter environment and command-line...
997 */
998
999 optstr = escape_options(num_options, options);
1000
e6013cfa 1001 snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
1340db2d 1002 srctype->super, srctype->type);
bc44d920 1003 snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
1004 snprintf(cups_fontpath, sizeof(cups_fontpath), "CUPS_FONTPATH=%s", FontPath);
1005 snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s",
1006 ServerBin);
1007 snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s",
1008 ServerRoot);
cc0d019f
MS
1009 language = cupsLangDefault();
1010 snprintf(lang, sizeof(lang), "LANG=%s.UTF8", language->language);
bc44d920 1011 snprintf(path, sizeof(path), "PATH=%s", Path);
1012 if (ppdfile)
1013 snprintf(ppd, sizeof(ppd), "PPD=%s", ppdfile);
1014 else if ((temp = getenv("PPD")) != NULL)
1015 snprintf(ppd, sizeof(ppd), "PPD=%s", temp);
1016 else
cc0d019f 1017#ifdef __APPLE__
db1f069b
MS
1018 if (!access("/System/Library/Frameworks/ApplicationServices.framework/"
1019 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
1020 "Resources/English.lproj/Generic.ppd", 0))
cc0d019f
MS
1021 strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
1022 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
1023 "Resources/English.lproj/Generic.ppd", sizeof(ppd));
db1f069b
MS
1024 else
1025 strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
1026 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
1027 "Resources/Generic.ppd", sizeof(ppd));
cc0d019f 1028#else
bc44d920 1029 snprintf(ppd, sizeof(ppd), "PPD=%s/model/laserjet.ppd", DataDir);
cc0d019f 1030#endif /* __APPLE__ */
71e16022 1031 snprintf(rip_max_cache, sizeof(rip_max_cache), "RIP_MAX_CACHE=%s", RIPCache);
cc0d019f 1032 snprintf(userenv, sizeof(userenv), "USER=%s", user);
bc44d920 1033
5a6b583a
MS
1034 if (printer &&
1035 (dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, NULL)) != NULL)
1036 {
1037 if ((temp = cupsGetOption("printer-info", dest->num_options,
1038 dest->options)) != NULL)
1039 snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", temp);
1040 else
1041 snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", printer);
1042
1043 if ((temp = cupsGetOption("printer-location", dest->num_options,
1044 dest->options)) != NULL)
1045 snprintf(printer_location, sizeof(printer_location),
1046 "PRINTER_LOCATION=%s", temp);
1047 else
1048 strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
1049 sizeof(printer_location));
1050 }
1051 else
1052 {
1053 snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s",
1054 printer ? printer : "Unknown");
1055 strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
1056 sizeof(printer_location));
1057 }
1058
1059 snprintf(printer_name, sizeof(printer_name), "PRINTER=%s",
1060 printer ? printer : "Unknown");
1061
db1f069b
MS
1062 argv[0] = (char *)printer;
1063 argv[1] = "1";
cc0d019f 1064 argv[2] = user;
bc44d920 1065 argv[3] = title;
1066 argv[4] = cupsGetOption("copies", num_options, options);
1067 argv[5] = optstr;
cc0d019f 1068 argv[6] = infile;
bc44d920 1069 argv[7] = NULL;
1070
1071 if (!argv[4])
1072 argv[4] = "1";
1073
1074 envp[0] = "<CFProcessPath>";
e6013cfa
MS
1075 envp[1] = content_type;
1076 envp[2] = cups_datadir;
1077 envp[3] = cups_fontpath;
1078 envp[4] = cups_serverbin;
1079 envp[5] = cups_serverroot;
1080 envp[6] = lang;
1081 envp[7] = path;
1082 envp[8] = ppd;
5a6b583a
MS
1083 envp[9] = printer_info;
1084 envp[10] = printer_location;
1085 envp[11] = printer_name;
71e16022 1086 envp[12] = rip_max_cache;
5a6b583a 1087 envp[13] = userenv;
c5b24bfa 1088 envp[14] = "CHARSET=utf-8";
6961465f
MS
1089 if (final_content_type[0])
1090 {
1091 envp[15] = final_content_type;
1092 envp[16] = NULL;
1093 }
1094 else
1095 envp[15] = NULL;
bc44d920 1096
cc0d019f
MS
1097 for (i = 0; argv[i]; i ++)
1098 fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
1099
1100 for (i = 0; envp[i]; i ++)
1101 fprintf(stderr, "DEBUG: envp[%d]=\"%s\"\n", i, envp[i]);
1102
bc44d920 1103 /*
1104 * Execute all of the filters...
1105 */
1106
1107 pids = cupsArrayNew((cups_array_func_t)compare_pids, NULL);
1108 current = 0;
1109 filterfds[0][0] = -1;
1110 filterfds[0][1] = -1;
1111 filterfds[1][0] = -1;
1112 filterfds[1][1] = -1;
1113
cc0d019f
MS
1114 if (!infile)
1115 filterfds[0][0] = 0;
1116
bc44d920 1117 for (filter = (mime_filter_t *)cupsArrayFirst(filters);
1118 filter;
1119 filter = next, current = 1 - current)
1120 {
1121 next = (mime_filter_t *)cupsArrayNext(filters);
1122
1123 if (filter->filter[0] == '/')
1124 strlcpy(program, filter->filter, sizeof(program));
1125 else
1126 snprintf(program, sizeof(program), "%s/filter/%s", ServerBin,
1127 filter->filter);
1128
1129 if (filterfds[!current][1] > 1)
1130 {
1131 close(filterfds[1 - current][0]);
1132 close(filterfds[1 - current][1]);
1133
1134 filterfds[1 - current][0] = -1;
1135 filterfds[1 - current][0] = -1;
1136 }
1137
1138 if (next)
1139 open_pipe(filterfds[1 - current]);
cc0d019f
MS
1140 else if (outfile)
1141 {
1142 filterfds[1 - current][1] = open(outfile, O_CREAT | O_TRUNC | O_WRONLY,
1143 0666);
1144
1145 if (filterfds[1 - current][1] < 0)
1146 fprintf(stderr, "ERROR: Unable to create \"%s\" - %s\n", outfile,
1147 strerror(errno));
1148 }
bc44d920 1149 else
1150 filterfds[1 - current][1] = 1;
1151
1152 pid = exec_filter(program, (char **)argv, (char **)envp,
1153 filterfds[current][0], filterfds[1 - current][1]);
1154
1155 if (pid > 0)
1156 {
1157 fprintf(stderr, "INFO: %s (PID %d) started.\n", filter->filter, pid);
1158
1159 filter->cost = pid;
1160 cupsArrayAdd(pids, filter);
1161 }
1162 else
1163 break;
1164
1165 argv[6] = NULL;
1166 }
1167
1168 /*
1169 * Close remaining pipes...
1170 */
1171
1172 if (filterfds[0][1] > 1)
1173 {
1174 close(filterfds[0][0]);
1175 close(filterfds[0][1]);
1176 }
1177
1178 if (filterfds[1][1] > 1)
1179 {
1180 close(filterfds[1][0]);
1181 close(filterfds[1][1]);
1182 }
1183
1184 /*
1185 * Wait for the children to exit...
1186 */
1187
1188 retval = 0;
1189
1190 while (cupsArrayCount(pids) > 0)
1191 {
1192 if ((pid = wait(&status)) < 0)
1193 continue;
1194
1195 key.cost = pid;
1196 if ((filter = (mime_filter_t *)cupsArrayFind(pids, &key)) != NULL)
1197 {
1198 cupsArrayRemove(pids, filter);
1199
1200 if (status)
1201 {
1202 if (WIFEXITED(status))
4d301e69 1203 fprintf(stderr, "ERROR: %s (PID %d) stopped with status %d\n",
bc44d920 1204 filter->filter, pid, WEXITSTATUS(status));
1205 else
4d301e69 1206 fprintf(stderr, "ERROR: %s (PID %d) crashed on signal %d\n",
bc44d920 1207 filter->filter, pid, WTERMSIG(status));
1208
1209 retval = 1;
1210 }
1211 else
1212 fprintf(stderr, "INFO: %s (PID %d) exited with no errors.\n",
1213 filter->filter, pid);
1214 }
1215 }
1216
91c84a35
MS
1217 cupsArrayDelete(pids);
1218
bc44d920 1219 return (retval);
1220}
1221
1222
2e4ff8af
MS
1223/*
1224 * 'get_job_file()' - Get the specified job file.
1225 */
1226
1227static void
1228get_job_file(const char *job) /* I - Job ID */
1229{
1230 long jobid, /* Job ID */
1231 docnum; /* Document number */
1232 const char *jobptr; /* Pointer into job ID string */
1233 char uri[1024]; /* job-uri */
1234 http_t *http; /* Connection to server */
1235 ipp_t *request; /* Request data */
1236 int tempfd; /* Temporary file */
1237
1238
1239 /*
1240 * Get the job ID and document number, if any...
1241 */
1242
1243 if ((jobptr = strrchr(job, '-')) != NULL)
1244 jobptr ++;
1245 else
1246 jobptr = job;
1247
1248 jobid = strtol(jobptr, (char **)&jobptr, 10);
1249
1250 if (*jobptr == ',')
1251 docnum = strtol(jobptr + 1, NULL, 10);
1252 else
1253 docnum = 1;
1254
1255 if (jobid < 1 || jobid > INT_MAX)
1256 {
0837b7e8 1257 _cupsLangPrintf(stderr, _("cupsfilter: Invalid job ID %d."), (int)jobid);
2e4ff8af
MS
1258 exit(1);
1259 }
1260
1261 if (docnum < 1 || docnum > INT_MAX)
1262 {
0837b7e8 1263 _cupsLangPrintf(stderr, _("cupsfilter: Invalid document number %d."),
2e4ff8af
MS
1264 (int)docnum);
1265 exit(1);
1266 }
1267
1268 /*
1269 * Ask the server for the document file...
1270 */
1271
1272 if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
1273 cupsEncryption())) == NULL)
1274 {
0837b7e8 1275 _cupsLangPrintf(stderr, _("%s: Unable to connect to server."),
2e4ff8af
MS
1276 "cupsfilter");
1277 exit(1);
1278 }
1279
1280 request = ippNewRequest(CUPS_GET_DOCUMENT);
1281
1282 snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", (int)jobid);
1283
1284 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
1285 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "document-number",
1286 (int)docnum);
1287
1288 if ((tempfd = cupsTempFd(TempFile, sizeof(TempFile))) == -1)
1289 {
0837b7e8 1290 _cupsLangPrintError("ERROR", _("Unable to create temporary file"));
2e4ff8af
MS
1291 httpClose(http);
1292 exit(1);
1293 }
1294
1295 signal(SIGTERM, sighandler);
1296
1297 ippDelete(cupsDoIORequest(http, request, "/", -1, tempfd));
1298
1299 close(tempfd);
1300
1301 httpClose(http);
1302
1303 if (cupsLastError() != IPP_OK)
1304 {
0837b7e8 1305 _cupsLangPrintf(stderr, _("cupsfilter: Unable to get job file - %s"),
2e4ff8af
MS
1306 cupsLastErrorString());
1307 unlink(TempFile);
1308 exit(1);
1309 }
1310}
1311
1312
bc44d920 1313/*
1314 * 'open_pipe()' - Create a pipe which is closed on exec.
1315 */
1316
2e4ff8af 1317static int /* O - 0 on success, -1 on error */
bc44d920 1318open_pipe(int *fds) /* O - Pipe file descriptors (2) */
1319{
1320 /*
1321 * Create the pipe...
1322 */
1323
1324 if (pipe(fds))
1325 {
1326 fds[0] = -1;
1327 fds[1] = -1;
1328
1329 return (-1);
1330 }
1331
1332 /*
1333 * Set the "close on exec" flag on each end of the pipe...
1334 */
1335
1336 if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
1337 {
1338 close(fds[0]);
1339 close(fds[1]);
1340
1341 fds[0] = -1;
1342 fds[1] = -1;
1343
1344 return (-1);
1345 }
1346
1347 if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
1348 {
1349 close(fds[0]);
1350 close(fds[1]);
1351
1352 fds[0] = -1;
1353 fds[1] = -1;
1354
1355 return (-1);
1356 }
1357
1358 /*
1359 * Return 0 indicating success...
1360 */
1361
1362 return (0);
1363}
1364
1365
1366/*
71f63681 1367 * 'read_cups_files_conf()' - Read the cups-files.conf file to get the filter settings.
bc44d920 1368 */
1369
1370static int /* O - 0 on success, 1 on error */
71f63681
MS
1371read_cups_files_conf(
1372 const char *filename) /* I - File to read */
bc44d920 1373{
71f63681 1374 cups_file_t *fp; /* cups-files.conf file */
bc44d920 1375 const char *temp; /* Temporary string */
1376 char line[1024], /* Line from file */
1377 *ptr; /* Pointer into line */
cc0d019f 1378 int linenum; /* Current line number */
bc44d920 1379
1380
1381 if ((temp = getenv("CUPS_DATADIR")) != NULL)
1382 set_string(&DataDir, temp);
1383 else
1384 set_string(&DataDir, CUPS_DATADIR);
1385
1386 if ((temp = getenv("CUPS_FONTPATH")) != NULL)
1387 set_string(&FontPath, temp);
1388 else
1389 set_string(&FontPath, CUPS_FONTPATH);
1390
eac3a0a0 1391 set_string(&RIPCache, "128m");
cc0d019f 1392
bc44d920 1393 if ((temp = getenv("CUPS_SERVERBIN")) != NULL)
1394 set_string(&ServerBin, temp);
1395 else
1396 set_string(&ServerBin, CUPS_SERVERBIN);
1397
1398 strlcpy(line, filename, sizeof(line));
1399 if ((ptr = strrchr(line, '/')) != NULL)
1400 *ptr = '\0';
1401 else
1402 getcwd(line, sizeof(line));
1403
1404 set_string(&ServerRoot, line);
1405
cc0d019f
MS
1406 if ((fp = cupsFileOpen(filename, "r")) != NULL)
1407 {
1408 linenum = 0;
1409
1410 while (cupsFileGetConf(fp, line, sizeof(line), &ptr, &linenum))
1411 {
88f9aafc 1412 if (!_cups_strcasecmp(line, "DataDir"))
cc0d019f 1413 set_string(&DataDir, ptr);
88f9aafc 1414 else if (!_cups_strcasecmp(line, "FontPath"))
cc0d019f 1415 set_string(&FontPath, ptr);
88f9aafc 1416 else if (!_cups_strcasecmp(line, "RIPCache"))
cc0d019f 1417 set_string(&RIPCache, ptr);
88f9aafc 1418 else if (!_cups_strcasecmp(line, "ServerBin"))
cc0d019f 1419 set_string(&ServerBin, ptr);
88f9aafc 1420 else if (!_cups_strcasecmp(line, "ServerRoot"))
cc0d019f
MS
1421 set_string(&ServerRoot, ptr);
1422 }
1423
1424 cupsFileClose(fp);
1425 }
1426
1a18c85c 1427 snprintf(line, sizeof(line), "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin);
bc44d920 1428 set_string(&Path, line);
1429
1430 return (0);
1431}
1432
1433
1434/*
1435 * 'set_string()' - Copy and set a string.
1436 */
1437
1438static void
1439set_string(char **s, /* O - Copy of string */
1440 const char *val) /* I - String to copy */
1441{
1442 if (*s)
1443 free(*s);
1444
1445 *s = strdup(val);
1446}
1447
1448
2e4ff8af
MS
1449/*
1450 * 'sighandler()' - Signal catcher for when we print from stdin...
1451 */
1452
1453static void
1454sighandler(int s) /* I - Signal number */
1455{
1456 /*
1457 * Remove the temporary file we're using to print a job file...
1458 */
1459
1460 if (TempFile[0])
1461 unlink(TempFile);
1462
1463 /*
1464 * Exit...
1465 */
1466
1467 exit(s);
1468}
1469
1470
bc44d920 1471/*
1472 * 'usage()' - Show program usage...
1473 */
1474
1475static void
f3c17241 1476usage(const char *opt) /* I - Incorrect option, if any */
bc44d920 1477{
1478 if (opt)
1a18c85c 1479 _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), "cupsfilter", *opt);
f3c17241 1480
1a18c85c 1481 _cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] [ -- ] filename"));
f3c17241 1482 _cupsLangPuts(stdout, _("Options:"));
1a18c85c
MS
1483 _cupsLangPuts(stdout, _(" --list-filters List filters that will be used."));
1484 _cupsLangPuts(stdout, _(" -D Remove the input file when finished."));
f3c17241
MS
1485 _cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file."));
1486 _cupsLangPuts(stdout, _(" -U username Specify username."));
1a18c85c
MS
1487 _cupsLangPuts(stdout, _(" -c cups-files.conf Set cups-files.conf file to use."));
1488 _cupsLangPuts(stdout, _(" -d printer Use the named printer."));
1489 _cupsLangPuts(stdout, _(" -e Use every filter from the PPD file."));
1490 _cupsLangPuts(stdout, _(" -i mime/type Set input MIME type (otherwise auto-typed)."));
1491 _cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the specified job (default is file 1)."));
1492 _cupsLangPuts(stdout, _(" -m mime/type Set output MIME type (otherwise application/pdf)."));
f3c17241
MS
1493 _cupsLangPuts(stdout, _(" -n copies Set number of copies."));
1494 _cupsLangPuts(stdout, _(" -o name=value Set option(s)."));
1495 _cupsLangPuts(stdout, _(" -p filename.ppd Set PPD file."));
1496 _cupsLangPuts(stdout, _(" -t title Set title."));
1a18c85c 1497 _cupsLangPuts(stdout, _(" -u Remove the PPD file when finished."));
bc44d920 1498
1499 exit(1);
1500}
1501
1502
1503/*
4ef75dec 1504 * End of "$Id: cupsfilter.c 12303 2014-12-09 16:16:07Z msweet $".
bc44d920 1505 */