]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cupsfilter.c
bcef6b951d2a28f506da3cf5298e37c20916538f
2 * "$Id: cupsfilter.c 7952 2008-09-17 00:56:20Z mike $"
4 * CUPS filtering program for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
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/".
17 * main() - Main entry for the test program.
18 * compare_pids() - Compare two filter PIDs...
19 * escape_options() - Convert an options array to a string.
20 * exec_filter() - Execute a single filter.
21 * exec_filters() - Execute filters for the given file and options.
22 * get_job_file() - Get the specified job file.
23 * open_pipe() - Create a pipe which is closed on exec.
24 * read_cupsd_conf() - Read the cupsd.conf file to get the filter settings.
25 * set_string() - Copy and set a string.
26 * usage() - Show program usage...
30 * Include necessary headers...
33 #include <cups/cups.h>
34 #include <cups/i18n.h>
35 #include <cups/string.h>
44 #if defined(__APPLE__)
46 #endif /* __APPLE__ */
53 static char *DataDir
= NULL
;/* CUPS_DATADIR environment variable */
54 static char *FontPath
= NULL
;
55 /* CUPS_FONTPATH environment variable */
56 static mime_filter_t GZIPFilter
= /* gziptoany filter */
58 NULL
, /* Source type */
59 NULL
, /* Destination type */
61 "gziptoany" /* Filter program to run */
63 static char *Path
= NULL
; /* PATH environment variable */
64 static char *ServerBin
= NULL
;
65 /* CUPS_SERVERBIN environment variable */
66 static char *ServerRoot
= NULL
;
67 /* CUPS_SERVERROOT environment variable */
68 static char *RIPCache
= NULL
;
69 /* RIP_CACHE environment variable */
70 static char TempFile
[1024] = "";
78 static void add_printer_filter(const char *command
, mime_t
*mime
,
79 mime_type_t
*printer_type
,
81 static mime_type_t
*add_printer_filters(const char *command
,
82 mime_t
*mime
, const char *printer
,
84 mime_type_t
**prefilter_type
);
85 static int compare_pids(mime_filter_t
*a
, mime_filter_t
*b
);
86 static char *escape_options(int num_options
, cups_option_t
*options
);
87 static int exec_filter(const char *filter
, char **argv
,
88 char **envp
, int infd
, int outfd
);
89 static int exec_filters(mime_type_t
*srctype
,
90 cups_array_t
*filters
, const char *infile
,
91 const char *outfile
, const char *ppdfile
,
92 const char *printer
, const char *user
,
93 const char *title
, int num_options
,
94 cups_option_t
*options
);
95 static void get_job_file(const char *job
);
96 static int open_pipe(int *fds
);
97 static int read_cupsd_conf(const char *filename
);
98 static void set_string(char **s
, const char *val
);
99 static void sighandler(int sig
);
100 static void usage(const char *command
, const char *opt
);
104 * 'main()' - Main entry for the test program.
107 int /* O - Exit status */
108 main(int argc
, /* I - Number of command-line args */
109 char *argv
[]) /* I - Command-line arguments */
111 int i
; /* Looping vars */
112 const char *command
, /* Command name */
113 *opt
, /* Current option */
114 *printer
; /* Printer name */
115 mime_type_t
*printer_type
, /* Printer MIME type */
116 *prefilter_type
; /* Printer prefilter MIME type */
117 char *srctype
, /* Source type */
118 *dsttype
, /* Destination type */
119 super
[MIME_MAX_SUPER
], /* Super-type name */
120 type
[MIME_MAX_TYPE
]; /* Type name */
121 int compression
; /* Compression of file */
122 int cost
; /* Cost of filters */
123 mime_t
*mime
; /* MIME database */
124 char mimedir
[1024]; /* MIME directory */
125 char *infile
, /* File to filter */
126 *outfile
; /* File to create */
127 char cupsdconf
[1024]; /* cupsd.conf file */
128 const char *server_root
; /* CUPS_SERVERROOT environment variable */
129 mime_type_t
*src
, /* Source type */
130 *dst
; /* Destination type */
131 cups_array_t
*filters
; /* Filters for the file */
132 int num_options
; /* Number of options */
133 cups_option_t
*options
; /* Options */
134 const char *ppdfile
; /* PPD file */
135 const char *title
, /* Title string */
136 *user
; /* Username */
137 int all_filters
, /* Use all filters */
138 removeppd
, /* Remove PPD file */
139 removeinfile
; /* Remove input file */
140 int status
; /* Execution status */
147 if ((command
= strrchr(argv
[0], '/')) != NULL
)
152 printer
= !strcmp(command
, "convert") ? "tofile" : "cupsfilter";
156 dsttype
= "application/pdf";
168 if ((server_root
= getenv("CUPS_SERVERROOT")) == NULL
)
169 server_root
= CUPS_SERVERROOT
;
171 snprintf(cupsdconf
, sizeof(cupsdconf
), "%s/cupsd.conf", server_root
);
174 * Process command-line arguments...
177 _cupsSetLocale(argv
);
179 for (i
= 1; i
< argc
; i
++)
180 if (argv
[i
][0] == '-')
182 for (opt
= argv
[i
] + 1; *opt
; opt
++)
185 case '-' : /* Next argument is a filename... */
187 if (i
< argc
&& !infile
)
193 case 'a' : /* Specify option... */
196 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
201 case 'c' : /* Specify cupsd.conf file location... */
205 if (!strcmp(command
, "convert"))
206 num_options
= cupsAddOption("copies", argv
[i
], num_options
,
209 strlcpy(cupsdconf
, argv
[i
], sizeof(cupsdconf
));
215 case 'd' : /* Specify the real printer name */
223 case 'D' : /* Delete input file after conversion */
227 case 'e' : /* Use every filter from the PPD file */
231 case 'f' : /* Specify input file... */
233 if (i
< argc
&& !infile
)
239 case 'i' : /* Specify source MIME type... */
243 if (sscanf(argv
[i
], "%15[^/]/%255s", super
, type
) != 2)
252 case 'j' : /* Get job file or specify destination MIME type... */
253 if (strcmp(command
, "convert"))
258 get_job_file(argv
[i
]);
267 case 'm' : /* Specify destination MIME type... */
271 if (sscanf(argv
[i
], "%15[^/]/%255s", super
, type
) != 2)
280 case 'n' : /* Specify number of copies... */
283 num_options
= cupsAddOption("copies", argv
[i
], num_options
,
289 case 'o' : /* Specify option(s) or output filename */
293 if (!strcmp(command
, "convert"))
296 usage(command
, NULL
);
301 num_options
= cupsParseOptions(argv
[i
], num_options
,
308 case 'p' : /* Specify PPD file... */
309 case 'P' : /* Specify PPD file... */
317 case 't' : /* Specify title... */
318 case 'J' : /* Specify title... */
326 case 'u' : /* Delete PPD file after conversion */
330 case 'U' : /* Specify username... */
338 default : /* Something we don't understand... */
345 if (strcmp(command
, "convert"))
349 _cupsLangPuts(stderr
,
350 _("convert: Use the -f option to specify a file to "
352 usage(command
, NULL
);
357 _cupsLangPuts(stderr
,
358 _("cupsfilter: Only one filename can be specified\n"));
359 usage(command
, NULL
);
362 if (!infile
&& !srctype
)
363 usage(command
, NULL
);
369 else if ((title
= strrchr(infile
, '/')) != NULL
)
376 * Load the cupsd.conf file and create the MIME database...
379 if (read_cupsd_conf(cupsdconf
))
382 snprintf(mimedir
, sizeof(mimedir
), "%s/mime", DataDir
);
384 mime
= mimeLoadTypes(NULL
, mimedir
);
385 mime
= mimeLoadTypes(mime
, ServerRoot
);
386 mime
= mimeLoadFilters(mime
, mimedir
, Path
);
387 mime
= mimeLoadFilters(mime
, ServerRoot
, Path
);
391 _cupsLangPrintf(stderr
,
392 _("%s: Unable to read MIME database from \"%s\" or "
394 command
, mimedir
, ServerRoot
);
400 printer_type
= add_printer_filters(command
, mime
, printer
, ppdfile
,
405 printer_type
= mimeType(mime
, "application", "vnd.cups-postscript");
406 prefilter_type
= NULL
;
410 * Get the source and destination types...
415 sscanf(srctype
, "%15[^/]/%255s", super
, type
);
416 if ((src
= mimeType(mime
, super
, type
)) == NULL
)
418 _cupsLangPrintf(stderr
,
419 _("%s: Unknown source MIME type %s/%s\n"),
420 command
, super
, type
);
424 else if ((src
= mimeFileType(mime
, infile
, infile
, &compression
)) == NULL
)
426 _cupsLangPrintf(stderr
,
427 _("%s: Unable to determine MIME type of \"%s\"\n"),
432 sscanf(dsttype
, "%15[^/]/%255s", super
, type
);
433 if (!strcasecmp(super
, "printer"))
435 else if ((dst
= mimeType(mime
, super
, type
)) == NULL
)
437 _cupsLangPrintf(stderr
,
438 _("%s: Unknown destination MIME type %s/%s\n"),
439 command
, super
, type
);
444 * Figure out how to filter the file...
450 * Special case - no filtering needed...
453 filters
= cupsArrayNew(NULL
, NULL
);
454 cupsArrayAdd(filters
, &GZIPFilter
);
455 GZIPFilter
.src
= src
;
456 GZIPFilter
.dst
= dst
;
458 else if ((filters
= mimeFilter(mime
, src
, dst
, &cost
)) == NULL
)
460 _cupsLangPrintf(stderr
,
461 _("%s: No filter to convert from %s/%s to %s/%s\n"),
462 command
, src
->super
, src
->type
, dst
->super
, dst
->type
);
465 else if (compression
)
466 cupsArrayInsert(filters
, &GZIPFilter
);
474 mime_filter_t
*filter
, /* Current filter */
475 *prefilter
; /* Current pre-filter */
476 cups_array_t
*prefilters
= cupsArrayNew(NULL
, NULL
);
477 /* New filters array */
480 for (filter
= (mime_filter_t
*)cupsArrayFirst(filters
);
482 filter
= (mime_filter_t
*)cupsArrayNext(filters
))
484 if ((prefilter
= mimeFilterLookup(mime
, filter
->src
,
485 prefilter_type
)) != NULL
)
486 cupsArrayAdd(prefilters
, prefilter
);
488 cupsArrayAdd(prefilters
, filter
);
491 cupsArrayDelete(filters
);
492 filters
= prefilters
;
499 status
= exec_filters(src
, filters
, infile
, outfile
, ppdfile
, printer
, user
,
500 title
, num_options
, options
);
503 * Remove files as needed, then exit...
509 if (removeppd
&& ppdfile
)
512 if (removeinfile
&& infile
)
520 * 'add_printer_filter()' - Add a single filters from a PPD file.
525 const char *command
, /* I - Command name */
526 mime_t
*mime
, /* I - MIME database */
527 mime_type_t
*filtertype
, /* I - Printer or prefilter MIME type */
528 const char *filter
) /* I - Filter to add */
530 char super
[MIME_MAX_SUPER
], /* Super-type for filter */
531 type
[MIME_MAX_TYPE
], /* Type for filter */
532 program
[1024]; /* Program/filter name */
533 int cost
; /* Cost of filter */
534 mime_type_t
*temptype
; /* MIME type looping var */
535 char filename
[1024]; /* Full filter filename */
539 * Parse the filter string; it should be in the following format:
541 * super/type cost program
544 if (sscanf(filter
, "%15[^/]/%31s%d%*[ \t]%1023[^\n]", super
, type
, &cost
,
547 _cupsLangPrintf(stderr
, _("%s: Invalid filter string \"%s\"\n"), command
,
553 * See if the filter program exists; if not, stop the printer and flag
557 if (strcmp(program
, "-"))
559 if (program
[0] == '/')
560 strlcpy(filename
, program
, sizeof(filename
));
562 snprintf(filename
, sizeof(filename
), "%s/filter/%s", ServerBin
, program
);
564 if (access(filename
, X_OK
))
566 _cupsLangPrintf(stderr
, _("%s: Filter \"%s\" not available: %s\n"),
567 command
, program
, strerror(errno
));
573 * Add the filter to the MIME database, supporting wildcards as needed...
576 for (temptype
= mimeFirstType(mime
);
578 temptype
= mimeNextType(mime
))
579 if (((super
[0] == '*' && strcasecmp(temptype
->super
, "printer")) ||
580 !strcasecmp(temptype
->super
, super
)) &&
581 (type
[0] == '*' || !strcasecmp(temptype
->type
, type
)))
582 mimeAddFilter(mime
, temptype
, filtertype
, cost
, program
);
587 * 'add_printer_filters()' - Add filters from a PPD file.
590 static mime_type_t
* /* O - Printer type or NULL on error */
592 const char *command
, /* I - Command name */
593 mime_t
*mime
, /* I - MIME database */
594 const char *printer
, /* I - Printer name */
595 const char *ppdfile
, /* I - PPD file */
596 mime_type_t
**prefilter_type
) /* O - Prefilter type */
598 int i
; /* Looping var */
599 mime_type_t
*printer_type
; /* Printer MIME type */
600 ppd_file_t
*ppd
; /* PPD file data */
601 ppd_attr_t
*ppdattr
; /* Current prefilter */
604 *prefilter_type
= NULL
;
606 if ((ppd
= ppdOpenFile(ppdfile
)) == NULL
)
608 ppd_status_t status
; /* PPD load status */
610 status
= ppdLastError(&i
);
611 _cupsLangPrintf(stderr
, _("%s: Unable to open PPD file: %s on line %d\n"),
612 command
, ppdErrorString(status
), i
);
616 printer_type
= mimeAddType(mime
, "printer", printer
);
618 if (ppd
->num_filters
> 0)
620 for (i
= 0; i
< ppd
->num_filters
; i
++)
621 add_printer_filter(command
, mime
, printer_type
, ppd
->filters
[i
]);
625 add_printer_filter(command
, mime
, printer_type
,
626 "application/vnd.cups-command 0 commandtops");
627 add_printer_filter(command
, mime
, printer_type
,
628 "application/vnd.cups-postscript 0 -");
631 if ((ppdattr
= ppdFindAttr(ppd
, "cupsPreFilter", NULL
)) != NULL
)
633 *prefilter_type
= mimeAddType(mime
, "prefilter", printer
);
635 for (; ppdattr
; ppdattr
= ppdFindNextAttr(ppd
, "cupsPreFilter", NULL
))
637 add_printer_filter(command
, mime
, *prefilter_type
, ppdattr
->value
);
640 *prefilter_type
= NULL
;
642 return (printer_type
);
647 * 'compare_pids()' - Compare two filter PIDs...
650 static int /* O - Result of comparison */
651 compare_pids(mime_filter_t
*a
, /* I - First filter */
652 mime_filter_t
*b
) /* I - Second filter */
655 * Because we're particularly lazy, we store the process ID in the "cost"
659 return (a
->cost
- b
->cost
);
664 * 'escape_options()' - Convert an options array to a string.
667 static char * /* O - Option string */
669 int num_options
, /* I - Number of options */
670 cups_option_t
*options
) /* I - Options */
672 int i
; /* Looping var */
673 cups_option_t
*option
; /* Current option */
674 int bytes
; /* Number of bytes needed */
675 char *s
, /* Option string */
676 *sptr
, /* Pointer into string */
677 *vptr
; /* Pointer into value */
681 * Figure out the worst-case number of bytes we need for the option string.
684 for (i
= num_options
, option
= options
, bytes
= 1; i
> 0; i
--, option
++)
685 bytes
+= 2 * (strlen(option
->name
) + strlen(option
->value
)) + 2;
687 if ((s
= malloc(bytes
)) == NULL
)
691 * Copy the options to the string...
694 for (i
= num_options
, option
= options
, sptr
= s
; i
> 0; i
--, option
++)
696 if (!strcmp(option
->name
, "copies"))
702 strcpy(sptr
, option
->name
);
703 sptr
+= strlen(sptr
);
706 for (vptr
= option
->value
; *vptr
;)
708 if (strchr("\\ \t\n", *vptr
))
722 * 'exec_filter()' - Execute a single filter.
725 static int /* O - Process ID or -1 on error */
726 exec_filter(const char *filter
, /* I - Filter to execute */
727 char **argv
, /* I - Argument list */
728 char **envp
, /* I - Environment list */
729 int infd
, /* I - Stdin file descriptor */
730 int outfd
) /* I - Stdout file descriptor */
732 int pid
, /* Process ID */
733 fd
; /* Temporary file descriptor */
734 #if defined(__APPLE__)
735 char processPath
[1024], /* CFProcessPath environment variable */
736 linkpath
[1024]; /* Link path for symlinks... */
737 int linkbytes
; /* Bytes for link path */
741 * Add special voodoo magic for MacOS X - this allows MacOS X
742 * programs to access their bundle resources properly...
745 if ((linkbytes
= readlink(filter
, linkpath
, sizeof(linkpath
) - 1)) > 0)
748 * Yes, this is a symlink to the actual program, nul-terminate and
752 linkpath
[linkbytes
] = '\0';
754 if (linkpath
[0] == '/')
755 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s",
758 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s/%s",
759 dirname((char *)filter
), linkpath
);
762 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s", filter
);
764 envp
[0] = processPath
; /* Replace <CFProcessPath> string */
765 #endif /* __APPLE__ */
767 if ((pid
= fork()) == 0)
770 * Child process goes here...
772 * Update stdin/stdout/stderr as needed...
778 infd
= open("/dev/null", O_RDONLY
);
790 outfd
= open("/dev/null", O_WRONLY
);
799 if ((fd
= open("/dev/null", O_RDWR
)) > 3)
804 fcntl(3, F_SETFL
, O_NDELAY
);
806 if ((fd
= open("/dev/null", O_RDWR
)) > 4)
811 fcntl(4, F_SETFL
, O_NDELAY
);
817 execve(filter
, argv
, envp
);
829 * 'exec_filters()' - Execute filters for the given file and options.
832 static int /* O - 0 on success, 1 on error */
833 exec_filters(mime_type_t
*srctype
, /* I - Source type */
834 cups_array_t
*filters
, /* I - Array of filters to run */
835 const char *infile
, /* I - File to filter */
836 const char *outfile
, /* I - File to create */
837 const char *ppdfile
, /* I - PPD file, if any */
838 const char *printer
, /* I - Printer name */
839 const char *user
, /* I - Username */
840 const char *title
, /* I - Job title */
841 int num_options
, /* I - Number of filter options */
842 cups_option_t
*options
) /* I - Filter options */
844 int i
; /* Looping var */
845 const char *argv
[8], /* Command-line arguments */
846 *envp
[15], /* Environment variables */
847 *temp
; /* Temporary string */
848 char *optstr
, /* Filter options */
849 content_type
[1024], /* CONTENT_TYPE */
850 cups_datadir
[1024], /* CUPS_DATADIR */
851 cups_fontpath
[1024], /* CUPS_FONTPATH */
852 cups_serverbin
[1024], /* CUPS_SERVERBIN */
853 cups_serverroot
[1024], /* CUPS_SERVERROOT */
854 lang
[1024], /* LANG */
855 path
[1024], /* PATH */
857 printer_info
[255], /* PRINTER_INFO env variable */
858 printer_location
[255], /* PRINTER_LOCATION env variable */
859 printer_name
[255], /* PRINTER env variable */
860 rip_cache
[1024], /* RIP_CACHE */
861 userenv
[1024], /* USER */
862 program
[1024]; /* Program to run */
863 mime_filter_t
*filter
, /* Current filter */
864 *next
; /* Next filter */
865 int current
, /* Current filter */
866 filterfds
[2][2], /* Pipes for filters */
867 pid
, /* Process ID of filter */
868 status
, /* Exit status */
869 retval
; /* Return value */
870 cups_array_t
*pids
; /* Executed filters array */
871 mime_filter_t key
; /* Search key for filters */
872 cups_lang_t
*language
; /* Current language */
873 cups_dest_t
*dest
; /* Destination information */
877 * Setup the filter environment and command-line...
880 optstr
= escape_options(num_options
, options
);
882 snprintf(content_type
, sizeof(content_type
), "CONTENT_TYPE=%s/%s",
883 srctype
->super
, srctype
->type
);
884 snprintf(cups_datadir
, sizeof(cups_datadir
), "CUPS_DATADIR=%s", DataDir
);
885 snprintf(cups_fontpath
, sizeof(cups_fontpath
), "CUPS_FONTPATH=%s", FontPath
);
886 snprintf(cups_serverbin
, sizeof(cups_serverbin
), "CUPS_SERVERBIN=%s",
888 snprintf(cups_serverroot
, sizeof(cups_serverroot
), "CUPS_SERVERROOT=%s",
890 language
= cupsLangDefault();
891 snprintf(lang
, sizeof(lang
), "LANG=%s.UTF8", language
->language
);
892 snprintf(path
, sizeof(path
), "PATH=%s", Path
);
894 snprintf(ppd
, sizeof(ppd
), "PPD=%s", ppdfile
);
895 else if ((temp
= getenv("PPD")) != NULL
)
896 snprintf(ppd
, sizeof(ppd
), "PPD=%s", temp
);
899 if (!access("/System/Library/Frameworks/ApplicationServices.framework/"
900 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
901 "Resources/English.lproj/Generic.ppd", 0))
902 strlcpy(ppd
, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
903 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
904 "Resources/English.lproj/Generic.ppd", sizeof(ppd
));
906 strlcpy(ppd
, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
907 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
908 "Resources/Generic.ppd", sizeof(ppd
));
910 snprintf(ppd
, sizeof(ppd
), "PPD=%s/model/laserjet.ppd", DataDir
);
911 #endif /* __APPLE__ */
912 snprintf(rip_cache
, sizeof(rip_cache
), "RIP_CACHE=%s", RIPCache
);
913 snprintf(userenv
, sizeof(userenv
), "USER=%s", user
);
916 (dest
= cupsGetNamedDest(CUPS_HTTP_DEFAULT
, printer
, NULL
)) != NULL
)
918 if ((temp
= cupsGetOption("printer-info", dest
->num_options
,
919 dest
->options
)) != NULL
)
920 snprintf(printer_info
, sizeof(printer_info
), "PRINTER_INFO=%s", temp
);
922 snprintf(printer_info
, sizeof(printer_info
), "PRINTER_INFO=%s", printer
);
924 if ((temp
= cupsGetOption("printer-location", dest
->num_options
,
925 dest
->options
)) != NULL
)
926 snprintf(printer_location
, sizeof(printer_location
),
927 "PRINTER_LOCATION=%s", temp
);
929 strlcpy(printer_location
, "PRINTER_LOCATION=Unknown",
930 sizeof(printer_location
));
934 snprintf(printer_info
, sizeof(printer_info
), "PRINTER_INFO=%s",
935 printer
? printer
: "Unknown");
936 strlcpy(printer_location
, "PRINTER_LOCATION=Unknown",
937 sizeof(printer_location
));
940 snprintf(printer_name
, sizeof(printer_name
), "PRINTER=%s",
941 printer
? printer
: "Unknown");
943 argv
[0] = (char *)printer
;
947 argv
[4] = cupsGetOption("copies", num_options
, options
);
955 envp
[0] = "<CFProcessPath>";
956 envp
[1] = content_type
;
957 envp
[2] = cups_datadir
;
958 envp
[3] = cups_fontpath
;
959 envp
[4] = cups_serverbin
;
960 envp
[5] = cups_serverroot
;
964 envp
[9] = printer_info
;
965 envp
[10] = printer_location
;
966 envp
[11] = printer_name
;
967 envp
[12] = rip_cache
;
971 for (i
= 0; argv
[i
]; i
++)
972 fprintf(stderr
, "DEBUG: argv[%d]=\"%s\"\n", i
, argv
[i
]);
974 for (i
= 0; envp
[i
]; i
++)
975 fprintf(stderr
, "DEBUG: envp[%d]=\"%s\"\n", i
, envp
[i
]);
978 * Execute all of the filters...
981 pids
= cupsArrayNew((cups_array_func_t
)compare_pids
, NULL
);
983 filterfds
[0][0] = -1;
984 filterfds
[0][1] = -1;
985 filterfds
[1][0] = -1;
986 filterfds
[1][1] = -1;
991 for (filter
= (mime_filter_t
*)cupsArrayFirst(filters
);
993 filter
= next
, current
= 1 - current
)
995 next
= (mime_filter_t
*)cupsArrayNext(filters
);
997 if (filter
->filter
[0] == '/')
998 strlcpy(program
, filter
->filter
, sizeof(program
));
1000 snprintf(program
, sizeof(program
), "%s/filter/%s", ServerBin
,
1003 if (filterfds
[!current
][1] > 1)
1005 close(filterfds
[1 - current
][0]);
1006 close(filterfds
[1 - current
][1]);
1008 filterfds
[1 - current
][0] = -1;
1009 filterfds
[1 - current
][0] = -1;
1013 open_pipe(filterfds
[1 - current
]);
1016 filterfds
[1 - current
][1] = open(outfile
, O_CREAT
| O_TRUNC
| O_WRONLY
,
1019 if (filterfds
[1 - current
][1] < 0)
1020 fprintf(stderr
, "ERROR: Unable to create \"%s\" - %s\n", outfile
,
1024 filterfds
[1 - current
][1] = 1;
1026 pid
= exec_filter(program
, (char **)argv
, (char **)envp
,
1027 filterfds
[current
][0], filterfds
[1 - current
][1]);
1031 fprintf(stderr
, "INFO: %s (PID %d) started.\n", filter
->filter
, pid
);
1034 cupsArrayAdd(pids
, filter
);
1043 * Close remaining pipes...
1046 if (filterfds
[0][1] > 1)
1048 close(filterfds
[0][0]);
1049 close(filterfds
[0][1]);
1052 if (filterfds
[1][1] > 1)
1054 close(filterfds
[1][0]);
1055 close(filterfds
[1][1]);
1059 * Wait for the children to exit...
1064 while (cupsArrayCount(pids
) > 0)
1066 if ((pid
= wait(&status
)) < 0)
1070 if ((filter
= (mime_filter_t
*)cupsArrayFind(pids
, &key
)) != NULL
)
1072 cupsArrayRemove(pids
, filter
);
1076 if (WIFEXITED(status
))
1077 fprintf(stderr
, "ERROR: %s (PID %d) stopped with status %d\n",
1078 filter
->filter
, pid
, WEXITSTATUS(status
));
1080 fprintf(stderr
, "ERROR: %s (PID %d) crashed on signal %d\n",
1081 filter
->filter
, pid
, WTERMSIG(status
));
1086 fprintf(stderr
, "INFO: %s (PID %d) exited with no errors.\n",
1087 filter
->filter
, pid
);
1091 cupsArrayDelete(pids
);
1098 * 'get_job_file()' - Get the specified job file.
1102 get_job_file(const char *job
) /* I - Job ID */
1104 long jobid
, /* Job ID */
1105 docnum
; /* Document number */
1106 const char *jobptr
; /* Pointer into job ID string */
1107 char uri
[1024]; /* job-uri */
1108 http_t
*http
; /* Connection to server */
1109 ipp_t
*request
; /* Request data */
1110 int tempfd
; /* Temporary file */
1114 * Get the job ID and document number, if any...
1117 if ((jobptr
= strrchr(job
, '-')) != NULL
)
1122 jobid
= strtol(jobptr
, (char **)&jobptr
, 10);
1125 docnum
= strtol(jobptr
+ 1, NULL
, 10);
1129 if (jobid
< 1 || jobid
> INT_MAX
)
1131 _cupsLangPrintf(stderr
, _("cupsfilter: Invalid job ID %d\n"), (int)jobid
);
1135 if (docnum
< 1 || docnum
> INT_MAX
)
1137 _cupsLangPrintf(stderr
, _("cupsfilter: Invalid document number %d\n"),
1143 * Ask the server for the document file...
1146 if ((http
= httpConnectEncrypt(cupsServer(), ippPort(),
1147 cupsEncryption())) == NULL
)
1149 _cupsLangPrintf(stderr
, _("%s: Unable to connect to server\n"),
1154 request
= ippNewRequest(CUPS_GET_DOCUMENT
);
1156 snprintf(uri
, sizeof(uri
), "ipp://localhost/jobs/%d", (int)jobid
);
1158 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
, uri
);
1159 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
, "document-number",
1162 if ((tempfd
= cupsTempFd(TempFile
, sizeof(TempFile
))) == -1)
1164 _cupsLangPrintError(_("ERROR: Unable to create temporary file"));
1169 signal(SIGTERM
, sighandler
);
1171 ippDelete(cupsDoIORequest(http
, request
, "/", -1, tempfd
));
1177 if (cupsLastError() != IPP_OK
)
1179 _cupsLangPrintf(stderr
, _("cupsfilter: Unable to get job file - %s\n"),
1180 cupsLastErrorString());
1188 * 'open_pipe()' - Create a pipe which is closed on exec.
1191 static int /* O - 0 on success, -1 on error */
1192 open_pipe(int *fds
) /* O - Pipe file descriptors (2) */
1195 * Create the pipe...
1207 * Set the "close on exec" flag on each end of the pipe...
1210 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
1221 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
1233 * Return 0 indicating success...
1241 * 'read_cupsd_conf()' - Read the cupsd.conf file to get the filter settings.
1244 static int /* O - 0 on success, 1 on error */
1245 read_cupsd_conf(const char *filename
) /* I - File to read */
1247 cups_file_t
*fp
; /* cupsd.conf file */
1248 const char *temp
; /* Temporary string */
1249 char line
[1024], /* Line from file */
1250 *ptr
; /* Pointer into line */
1251 int linenum
; /* Current line number */
1254 if ((temp
= getenv("CUPS_DATADIR")) != NULL
)
1255 set_string(&DataDir
, temp
);
1257 set_string(&DataDir
, CUPS_DATADIR
);
1259 if ((temp
= getenv("CUPS_FONTPATH")) != NULL
)
1260 set_string(&FontPath
, temp
);
1262 set_string(&FontPath
, CUPS_FONTPATH
);
1264 set_string(&RIPCache
, "8m");
1266 if ((temp
= getenv("CUPS_SERVERBIN")) != NULL
)
1267 set_string(&ServerBin
, temp
);
1269 set_string(&ServerBin
, CUPS_SERVERBIN
);
1271 strlcpy(line
, filename
, sizeof(line
));
1272 if ((ptr
= strrchr(line
, '/')) != NULL
)
1275 getcwd(line
, sizeof(line
));
1277 set_string(&ServerRoot
, line
);
1279 if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
1283 while (cupsFileGetConf(fp
, line
, sizeof(line
), &ptr
, &linenum
))
1285 if (!strcasecmp(line
, "DataDir"))
1286 set_string(&DataDir
, ptr
);
1287 else if (!strcasecmp(line
, "FontPath"))
1288 set_string(&FontPath
, ptr
);
1289 else if (!strcasecmp(line
, "RIPCache"))
1290 set_string(&RIPCache
, ptr
);
1291 else if (!strcasecmp(line
, "ServerBin"))
1292 set_string(&ServerBin
, ptr
);
1293 else if (!strcasecmp(line
, "ServerRoot"))
1294 set_string(&ServerRoot
, ptr
);
1300 snprintf(line
, sizeof(line
),
1301 "%s/filter:" CUPS_BINDIR
":" CUPS_SBINDIR
":/bin:/usr/bin",
1303 set_string(&Path
, line
);
1310 * 'set_string()' - Copy and set a string.
1314 set_string(char **s
, /* O - Copy of string */
1315 const char *val
) /* I - String to copy */
1325 * 'sighandler()' - Signal catcher for when we print from stdin...
1329 sighandler(int s
) /* I - Signal number */
1332 * Remove the temporary file we're using to print a job file...
1347 * 'usage()' - Show program usage...
1351 usage(const char *command
, /* I - Command name */
1352 const char *opt
) /* I - Incorrect option, if any */
1355 _cupsLangPrintf(stderr
, _("%s: Unknown option '%c'\n"), command
, *opt
);
1357 if (!strcmp(command
, "cupsfilter"))
1358 _cupsLangPuts(stdout
,
1359 _("Usage: cupsfilter -m mime/type [ options ] filename\n"
1363 " -c cupsd.conf Set cupsd.conf file to use\n"
1364 " -d printer Use the named printer\n"
1365 " -e Use every filter from the PPD file\n"
1366 " -j job-id[,N] Filter file N from the specified job (default is file 1)\n"
1367 " -n copies Set number of copies\n"
1368 " -o name=value Set option(s)\n"
1369 " -p filename.ppd Set PPD file\n"
1370 " -t title Set title\n"));
1372 _cupsLangPuts(stdout
,
1373 _("Usage: convert [ options ]\n"
1377 " -d printer Use the named printer\n"
1378 " -e Use every filter from the PPD file\n"
1379 " -f filename Set file to be converted (otherwise stdin)\n"
1380 " -o filename Set file to be generated (otherwise stdout)\n"
1381 " -i mime/type Set input MIME type (otherwise auto-typed)\n"
1382 " -j mime/type Set output MIME type (otherwise application/pdf)\n"
1383 " -P filename.ppd Set PPD file\n"
1384 " -a 'name=value ...' Set option(s)\n"
1385 " -U username Set username for job\n"
1386 " -J title Set title\n"
1387 " -c copies Set number of copies\n"
1388 " -u Remove the PPD file when finished\n"
1389 " -D Remove the input file when finished\n"));
1396 * End of "$Id: cupsfilter.c 7952 2008-09-17 00:56:20Z mike $".