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