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