blob: 4085be18fc4dda9af352bd43fee9035d35d641a8 [file] [log] [blame]
/*
* "$Id: cupsfilter.c 6879 2007-08-29 20:26:50Z mike $"
*
* CUPS filtering program for the Common UNIX Printing System (CUPS).
*
* Copyright 2007 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
* which should have been included with this file. If this file is
* file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
* main() - Main entry for the test program.
* compare_pids() - Compare two filter PIDs...
* escape_options() - Convert an options array to a string.
* exec_filter() - Execute a single filter.
* exec_filters() - Execute filters for the given file and options.
* get_job_file() - Get the specified job file.
* open_pipe() - Create a pipe which is closed on exec.
* read_cupsd_conf() - Read the cupsd.conf file to get the filter settings.
* set_string() - Copy and set a string.
* usage() - Show program usage...
*/
/*
* Include necessary headers...
*/
#include <cups/cups.h>
#include <cups/i18n.h>
#include <cups/string.h>
#include <errno.h>
#include "mime.h"
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#if defined(__APPLE__)
# include <libgen.h>
#endif /* __APPLE__ */
/*
* Local globals...
*/
static char *DataDir = NULL;/* CUPS_DATADIR environment variable */
static char *FontPath = NULL;
/* CUPS_FONTPATH environment variable */
static mime_filter_t GZIPFilter = /* gziptoany filter */
{
NULL, /* Source type */
NULL, /* Destination type */
0, /* Cost */
"gziptoany" /* Filter program to run */
};
static char *Path = NULL; /* PATH environment variable */
static char *ServerBin = NULL;
/* CUPS_SERVERBIN environment variable */
static char *ServerRoot = NULL;
/* CUPS_SERVERROOT environment variable */
static char *RIPCache = NULL;
/* RIP_CACHE environment variable */
static char TempFile[1024] = "";
/* Temporary file */
/*
* Local functions...
*/
static int compare_pids(mime_filter_t *a, mime_filter_t *b);
static char *escape_options(int num_options, cups_option_t *options);
static int exec_filter(const char *filter, char **argv, char **envp,
int infd, int outfd);
static int exec_filters(cups_array_t *filters, const char *infile,
const char *outfile, const char *ppdfile,
const char *printer, const char *user,
const char *title, int num_options,
cups_option_t *options);
static void get_job_file(const char *job);
static int open_pipe(int *fds);
static int read_cupsd_conf(const char *filename);
static void set_string(char **s, const char *val);
static void sighandler(int sig);
static void usage(const char *command, const char *opt);
/*
* 'main()' - Main entry for the test program.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line args */
char *argv[]) /* I - Command-line arguments */
{
int i; /* Looping vars */
const char *command, /* Command name */
*opt; /* Current option */
char *srctype, /* Source type */
*dsttype, /* Destination type */
super[MIME_MAX_SUPER], /* Super-type name */
type[MIME_MAX_TYPE]; /* Type name */
int compression; /* Compression of file */
int cost; /* Cost of filters */
mime_t *mime; /* MIME database */
char *infile, /* File to filter */
*outfile; /* File to create */
char cupsdconf[1024]; /* cupsd.conf file */
const char *server_root; /* CUPS_SERVERROOT environment variable */
mime_type_t *src, /* Source type */
*dst; /* Destination type */
cups_array_t *filters; /* Filters for the file */
int num_options; /* Number of options */
cups_option_t *options; /* Options */
const char *ppdfile; /* PPD file */
const char *title, /* Title string */
*user; /* Username */
int removeppd, /* Remove PPD file */
removeinfile; /* Remove input file */
int status; /* Execution status */
/*
* Setup defaults...
*/
if ((command = strrchr(argv[0], '/')) != NULL)
command ++;
else
command = argv[0];
mime = NULL;
srctype = NULL;
dsttype = "application/pdf";
infile = NULL;
outfile = NULL;
num_options = 0;
options = NULL;
ppdfile = NULL;
title = NULL;
user = cupsUser();
removeppd = 0;
removeinfile = 0;
if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
server_root = CUPS_SERVERROOT;
snprintf(cupsdconf, sizeof(cupsdconf), "%s/cupsd.conf", server_root);
/*
* Process command-line arguments...
*/
_cupsSetLocale(argv);
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
{
for (opt = argv[i] + 1; *opt; opt ++)
switch (*opt)
{
case '-' : /* Next argument is a filename... */
i ++;
if (i < argc && !infile)
infile = argv[i];
else
usage(command, opt);
break;
case 'a' : /* Specify option... */
i ++;
if (i < argc)
num_options = cupsParseOptions(argv[i], num_options, &options);
else
usage(command, opt);
break;
case 'c' : /* Specify cupsd.conf file location... */
i ++;
if (i < argc)
{
if (!strcmp(command, "convert"))
num_options = cupsAddOption("copies", argv[i], num_options,
&options);
else
strlcpy(cupsdconf, argv[i], sizeof(cupsdconf));
}
else
usage(command, opt);
break;
case 'D' : /* Delete input file after conversion */
removeinfile = 1;
break;
case 'f' : /* Specify input file... */
i ++;
if (i < argc && !infile)
infile = argv[i];
else
usage(command, opt);
break;
case 'i' : /* Specify source MIME type... */
i ++;
if (i < argc)
{
if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
usage(command, opt);
srctype = argv[i];
}
else
usage(command, opt);
break;
case 'j' : /* Get job file or specify destination MIME type... */
if (strcmp(command, "convert"))
{
i ++;
if (i < argc)
{
get_job_file(argv[i]);
infile = TempFile;
}
else
usage(command, opt);
break;
}
case 'm' : /* Specify destination MIME type... */
i ++;
if (i < argc)
{
if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
usage(command, opt);
dsttype = argv[i];
}
else
usage(command, opt);
break;
case 'n' : /* Specify number of copies... */
i ++;
if (i < argc)
num_options = cupsAddOption("copies", argv[i], num_options,
&options);
else
usage(command, opt);
break;
case 'o' : /* Specify option(s) or output filename */
i ++;
if (i < argc)
{
if (!strcmp(command, "convert"))
{
if (outfile)
usage(command, NULL);
else
outfile = argv[i];
}
else
num_options = cupsParseOptions(argv[i], num_options,
&options);
}
else
usage(command, opt);
break;
case 'p' : /* Specify PPD file... */
case 'P' : /* Specify PPD file... */
i ++;
if (i < argc)
ppdfile = argv[i];
else
usage(command, opt);
break;
case 't' : /* Specify title... */
case 'J' : /* Specify title... */
i ++;
if (i < argc)
title = argv[i];
else
usage(command, opt);
break;
case 'u' : /* Delete PPD file after conversion */
removeinfile = 1;
break;
case 'U' : /* Specify username... */
i ++;
if (i < argc)
user = argv[i];
else
usage(command, opt);
break;
default : /* Something we don't understand... */
usage(command, opt);
break;
}
}
else if (!infile)
{
if (strcmp(command, "convert"))
infile = argv[i];
else
{
_cupsLangPuts(stderr,
_("convert: Use the -f option to specify a file to "
"convert.\n"));
usage(command, NULL);
}
}
else
{
_cupsLangPuts(stderr,
_("cupsfilter: Only one filename can be specified!\n"));
usage(command, NULL);
}
if (!infile && !srctype)
usage(command, NULL);
if (!title)
{
if (!infile)
title = "(stdin)";
else if ((title = strrchr(infile, '/')) != NULL)
title ++;
else
title = infile;
}
/*
* Load the cupsd.conf file and create the MIME database...
*/
if (read_cupsd_conf(cupsdconf))
return (1);
if ((mime = mimeLoad(ServerRoot, Path)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unable to read MIME database from \"%s\"!\n"),
command, ServerRoot);
return (1);
}
/*
* Get the source and destination types...
*/
if (srctype)
{
sscanf(srctype, "%15[^/]/%255s", super, type);
if ((src = mimeType(mime, super, type)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unknown source MIME type %s/%s!\n"),
command, super, type);
return (1);
}
}
else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unable to determine MIME type of \"%s\"!\n"),
command, infile);
return (1);
}
sscanf(dsttype, "%15[^/]/%255s", super, type);
if ((dst = mimeType(mime, super, type)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unknown destination MIME type %s/%s!\n"),
command, super, type);
return (1);
}
/*
* Figure out how to filter the file...
*/
if (src == dst)
{
/*
* Special case - no filtering needed...
*/
filters = cupsArrayNew(NULL, NULL);
cupsArrayAdd(filters, &GZIPFilter);
}
else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: No filter to convert from %s/%s to %s/%s!\n"),
command, src->super, src->type, dst->super, dst->type);
return (1);
}
else if (compression)
cupsArrayInsert(filters, &GZIPFilter);
/*
* Do it!
*/
status = exec_filters(filters, infile, outfile, ppdfile,
!strcmp(command, "convert") ? "tofile" : "cupsfilter",
user, title, num_options, options);
/*
* Remove files as needed, then exit...
*/
if (TempFile[0])
unlink(TempFile);
if (removeppd && ppdfile)
unlink(ppdfile);
if (removeinfile && infile)
unlink(infile);
return (status);
}
/*
* 'compare_pids()' - Compare two filter PIDs...
*/
static int /* O - Result of comparison */
compare_pids(mime_filter_t *a, /* I - First filter */
mime_filter_t *b) /* I - Second filter */
{
/*
* Because we're particularly lazy, we store the process ID in the "cost"
* variable...
*/
return (a->cost - b->cost);
}
/*
* 'escape_options()' - Convert an options array to a string.
*/
static char * /* O - Option string */
escape_options(
int num_options, /* I - Number of options */
cups_option_t *options) /* I - Options */
{
int i; /* Looping var */
cups_option_t *option; /* Current option */
int bytes; /* Number of bytes needed */
char *s, /* Option string */
*sptr, /* Pointer into string */
*vptr; /* Pointer into value */
/*
* Figure out the worst-case number of bytes we need for the option string.
*/
for (i = num_options, option = options, bytes = 1; i > 0; i --, option ++)
bytes += 2 * (strlen(option->name) + strlen(option->value)) + 2;
s = malloc(bytes);
/*
* Copy the options to the string...
*/
for (i = num_options, option = options, sptr = s; i > 0; i --, option ++)
{
if (!strcmp(option->name, "copies"))
continue;
if (sptr > s)
*sptr++ = ' ';
strcpy(sptr, option->name);
sptr += strlen(sptr);
*sptr++ = '=';
for (vptr = option->value; *vptr;)
{
if (strchr("\\ \t\n", *vptr))
*sptr++ = '\\';
*sptr++ = *vptr++;
}
}
*sptr = '\0';
return (s);
}
/*
* 'exec_filter()' - Execute a single filter.
*/
static int /* O - Process ID or -1 on error */
exec_filter(const char *filter, /* I - Filter to execute */
char **argv, /* I - Argument list */
char **envp, /* I - Environment list */
int infd, /* I - Stdin file descriptor */
int outfd) /* I - Stdout file descriptor */
{
int pid; /* Process ID */
#if defined(__APPLE__)
char processPath[1024], /* CFProcessPath environment variable */
linkpath[1024]; /* Link path for symlinks... */
int linkbytes; /* Bytes for link path */
/*
* Add special voodoo magic for MacOS X - this allows MacOS X
* programs to access their bundle resources properly...
*/
if ((linkbytes = readlink(filter, linkpath, sizeof(linkpath) - 1)) > 0)
{
/*
* Yes, this is a symlink to the actual program, nul-terminate and
* use it...
*/
linkpath[linkbytes] = '\0';
if (linkpath[0] == '/')
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s",
linkpath);
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
dirname((char *)filter), linkpath);
}
else
snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", filter);
envp[0] = processPath; /* Replace <CFProcessPath> string */
#endif /* __APPLE__ */
if ((pid = fork()) == 0)
{
/*
* Child process goes here...
*
* Update stdin/stdout/stderr as needed...
*/
if (infd != 0)
{
close(0);
if (infd > 0)
dup(infd);
else
open("/dev/null", O_RDONLY);
}
if (outfd != 1)
{
close(1);
if (outfd > 0)
dup(outfd);
else
open("/dev/null", O_WRONLY);
}
close(3);
open("/dev/null", O_RDWR);
fcntl(3, F_SETFL, O_NDELAY);
close(4);
open("/dev/null", O_RDWR);
fcntl(4, F_SETFL, O_NDELAY);
/*
* Execute command...
*/
execve(filter, argv, envp);
perror(filter);
exit(errno);
}
return (pid);
}
/*
* 'exec_filters()' - Execute filters for the given file and options.
*/
static int /* O - 0 on success, 1 on error */
exec_filters(cups_array_t *filters, /* I - Array of filters to run */
const char *infile, /* I - File to filter */
const char *outfile, /* I - File to create */
const char *ppdfile, /* I - PPD file, if any */
const char *printer, /* I - Printer name */
const char *user, /* I - Username */
const char *title, /* I - Job title */
int num_options, /* I - Number of filter options */
cups_option_t *options) /* I - Filter options */
{
int i; /* Looping var */
const char *argv[8], /* Command-line arguments */
*envp[11], /* Environment variables */
*temp; /* Temporary string */
char *optstr, /* Filter options */
cups_datadir[1024], /* CUPS_DATADIR */
cups_fontpath[1024], /* CUPS_FONTPATH */
cups_serverbin[1024], /* CUPS_SERVERBIN */
cups_serverroot[1024], /* CUPS_SERVERROOT */
lang[1024], /* LANG */
path[1024], /* PATH */
ppd[1024], /* PPD */
rip_cache[1024], /* RIP_CACHE */
userenv[1024], /* USER */
program[1024]; /* Program to run */
mime_filter_t *filter, /* Current filter */
*next; /* Next filter */
int current, /* Current filter */
filterfds[2][2], /* Pipes for filters */
pid, /* Process ID of filter */
status, /* Exit status */
retval; /* Return value */
cups_array_t *pids; /* Executed filters array */
mime_filter_t key; /* Search key for filters */
cups_lang_t *language; /* Current language */
/*
* Setup the filter environment and command-line...
*/
optstr = escape_options(num_options, options);
snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
snprintf(cups_fontpath, sizeof(cups_fontpath), "CUPS_FONTPATH=%s", FontPath);
snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s",
ServerBin);
snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s",
ServerRoot);
language = cupsLangDefault();
snprintf(lang, sizeof(lang), "LANG=%s.UTF8", language->language);
snprintf(path, sizeof(path), "PATH=%s", Path);
if (ppdfile)
snprintf(ppd, sizeof(ppd), "PPD=%s", ppdfile);
else if ((temp = getenv("PPD")) != NULL)
snprintf(ppd, sizeof(ppd), "PPD=%s", temp);
else
#ifdef __APPLE__
if (!access("/System/Library/Frameworks/ApplicationServices.framework/"
"Versions/A/Frameworks/PrintCore.framework/Versions/A/"
"Resources/English.lproj/Generic.ppd", 0))
strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
"Versions/A/Frameworks/PrintCore.framework/Versions/A/"
"Resources/English.lproj/Generic.ppd", sizeof(ppd));
else
strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
"Versions/A/Frameworks/PrintCore.framework/Versions/A/"
"Resources/Generic.ppd", sizeof(ppd));
#else
snprintf(ppd, sizeof(ppd), "PPD=%s/model/laserjet.ppd", DataDir);
#endif /* __APPLE__ */
snprintf(rip_cache, sizeof(rip_cache), "RIP_CACHE=%s", RIPCache);
snprintf(userenv, sizeof(userenv), "USER=%s", user);
argv[0] = (char *)printer;
argv[1] = "1";
argv[2] = user;
argv[3] = title;
argv[4] = cupsGetOption("copies", num_options, options);
argv[5] = optstr;
argv[6] = infile;
argv[7] = NULL;
if (!argv[4])
argv[4] = "1";
envp[0] = "<CFProcessPath>";
envp[1] = cups_datadir;
envp[2] = cups_fontpath;
envp[3] = cups_serverbin;
envp[4] = cups_serverroot;
envp[5] = lang;
envp[6] = path;
envp[7] = ppd;
envp[8] = rip_cache;
envp[9] = userenv;
envp[10] = NULL;
for (i = 0; argv[i]; i ++)
fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
for (i = 0; envp[i]; i ++)
fprintf(stderr, "DEBUG: envp[%d]=\"%s\"\n", i, envp[i]);
/*
* Execute all of the filters...
*/
pids = cupsArrayNew((cups_array_func_t)compare_pids, NULL);
current = 0;
filterfds[0][0] = -1;
filterfds[0][1] = -1;
filterfds[1][0] = -1;
filterfds[1][1] = -1;
if (!infile)
filterfds[0][0] = 0;
for (filter = (mime_filter_t *)cupsArrayFirst(filters);
filter;
filter = next, current = 1 - current)
{
next = (mime_filter_t *)cupsArrayNext(filters);
if (filter->filter[0] == '/')
strlcpy(program, filter->filter, sizeof(program));
else
snprintf(program, sizeof(program), "%s/filter/%s", ServerBin,
filter->filter);
if (filterfds[!current][1] > 1)
{
close(filterfds[1 - current][0]);
close(filterfds[1 - current][1]);
filterfds[1 - current][0] = -1;
filterfds[1 - current][0] = -1;
}
if (next)
open_pipe(filterfds[1 - current]);
else if (outfile)
{
filterfds[1 - current][1] = open(outfile, O_CREAT | O_TRUNC | O_WRONLY,
0666);
if (filterfds[1 - current][1] < 0)
fprintf(stderr, "ERROR: Unable to create \"%s\" - %s\n", outfile,
strerror(errno));
}
else
filterfds[1 - current][1] = 1;
pid = exec_filter(program, (char **)argv, (char **)envp,
filterfds[current][0], filterfds[1 - current][1]);
if (pid > 0)
{
fprintf(stderr, "INFO: %s (PID %d) started.\n", filter->filter, pid);
filter->cost = pid;
cupsArrayAdd(pids, filter);
}
else
break;
argv[6] = NULL;
}
/*
* Close remaining pipes...
*/
if (filterfds[0][1] > 1)
{
close(filterfds[0][0]);
close(filterfds[0][1]);
}
if (filterfds[1][1] > 1)
{
close(filterfds[1][0]);
close(filterfds[1][1]);
}
/*
* Wait for the children to exit...
*/
retval = 0;
while (cupsArrayCount(pids) > 0)
{
if ((pid = wait(&status)) < 0)
continue;
key.cost = pid;
if ((filter = (mime_filter_t *)cupsArrayFind(pids, &key)) != NULL)
{
cupsArrayRemove(pids, filter);
if (status)
{
if (WIFEXITED(status))
fprintf(stderr, "ERROR: %s (PID %d) stopped with status %d!\n",
filter->filter, pid, WEXITSTATUS(status));
else
fprintf(stderr, "ERROR: %s (PID %d) crashed on signal %d!\n",
filter->filter, pid, WTERMSIG(status));
retval = 1;
}
else
fprintf(stderr, "INFO: %s (PID %d) exited with no errors.\n",
filter->filter, pid);
}
}
return (retval);
}
/*
* 'get_job_file()' - Get the specified job file.
*/
static void
get_job_file(const char *job) /* I - Job ID */
{
long jobid, /* Job ID */
docnum; /* Document number */
const char *jobptr; /* Pointer into job ID string */
char uri[1024]; /* job-uri */
http_t *http; /* Connection to server */
ipp_t *request; /* Request data */
int tempfd; /* Temporary file */
/*
* Get the job ID and document number, if any...
*/
if ((jobptr = strrchr(job, '-')) != NULL)
jobptr ++;
else
jobptr = job;
jobid = strtol(jobptr, (char **)&jobptr, 10);
if (*jobptr == ',')
docnum = strtol(jobptr + 1, NULL, 10);
else
docnum = 1;
if (jobid < 1 || jobid > INT_MAX)
{
_cupsLangPrintf(stderr, _("cupsfilter: Invalid job ID %d!\n"), (int)jobid);
exit(1);
}
if (docnum < 1 || docnum > INT_MAX)
{
_cupsLangPrintf(stderr, _("cupsfilter: Invalid document number %d!\n"),
(int)docnum);
exit(1);
}
/*
* Ask the server for the document file...
*/
if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
cupsEncryption())) == NULL)
{
_cupsLangPrintf(stderr, _("%s: Unable to connect to server\n"),
"cupsfilter");
exit(1);
}
request = ippNewRequest(CUPS_GET_DOCUMENT);
snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", (int)jobid);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "document-number",
(int)docnum);
if ((tempfd = cupsTempFd(TempFile, sizeof(TempFile))) == -1)
{
_cupsLangPrintf(stderr,
_("cupsfilter: Unable to create temporary file: %s\n"),
strerror(errno));
httpClose(http);
exit(1);
}
signal(SIGTERM, sighandler);
ippDelete(cupsDoIORequest(http, request, "/", -1, tempfd));
close(tempfd);
httpClose(http);
if (cupsLastError() != IPP_OK)
{
_cupsLangPrintf(stderr, _("cupsfilter: Unable to get job file - %s\n"),
cupsLastErrorString());
unlink(TempFile);
exit(1);
}
}
/*
* 'open_pipe()' - Create a pipe which is closed on exec.
*/
static int /* O - 0 on success, -1 on error */
open_pipe(int *fds) /* O - Pipe file descriptors (2) */
{
/*
* Create the pipe...
*/
if (pipe(fds))
{
fds[0] = -1;
fds[1] = -1;
return (-1);
}
/*
* Set the "close on exec" flag on each end of the pipe...
*/
if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
{
close(fds[0]);
close(fds[1]);
fds[0] = -1;
fds[1] = -1;
return (-1);
}
if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
{
close(fds[0]);
close(fds[1]);
fds[0] = -1;
fds[1] = -1;
return (-1);
}
/*
* Return 0 indicating success...
*/
return (0);
}
/*
* 'read_cupsd_conf()' - Read the cupsd.conf file to get the filter settings.
*/
static int /* O - 0 on success, 1 on error */
read_cupsd_conf(const char *filename) /* I - File to read */
{
cups_file_t *fp; /* cupsd.conf file */
const char *temp; /* Temporary string */
char line[1024], /* Line from file */
*ptr; /* Pointer into line */
int linenum; /* Current line number */
if ((temp = getenv("CUPS_DATADIR")) != NULL)
set_string(&DataDir, temp);
else
set_string(&DataDir, CUPS_DATADIR);
if ((temp = getenv("CUPS_FONTPATH")) != NULL)
set_string(&FontPath, temp);
else
set_string(&FontPath, CUPS_FONTPATH);
set_string(&RIPCache, "8m");
if ((temp = getenv("CUPS_SERVERBIN")) != NULL)
set_string(&ServerBin, temp);
else
set_string(&ServerBin, CUPS_SERVERBIN);
strlcpy(line, filename, sizeof(line));
if ((ptr = strrchr(line, '/')) != NULL)
*ptr = '\0';
else
getcwd(line, sizeof(line));
set_string(&ServerRoot, line);
if ((fp = cupsFileOpen(filename, "r")) != NULL)
{
linenum = 0;
while (cupsFileGetConf(fp, line, sizeof(line), &ptr, &linenum))
{
if (!strcasecmp(line, "DataDir"))
set_string(&DataDir, ptr);
else if (!strcasecmp(line, "FontPath"))
set_string(&FontPath, ptr);
else if (!strcasecmp(line, "RIPCache"))
set_string(&RIPCache, ptr);
else if (!strcasecmp(line, "ServerBin"))
set_string(&ServerBin, ptr);
else if (!strcasecmp(line, "ServerRoot"))
set_string(&ServerRoot, ptr);
}
cupsFileClose(fp);
}
snprintf(line, sizeof(line),
"%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin/usr/bin",
ServerBin);
set_string(&Path, line);
return (0);
}
/*
* 'set_string()' - Copy and set a string.
*/
static void
set_string(char **s, /* O - Copy of string */
const char *val) /* I - String to copy */
{
if (*s)
free(*s);
*s = strdup(val);
}
/*
* 'sighandler()' - Signal catcher for when we print from stdin...
*/
static void
sighandler(int s) /* I - Signal number */
{
/*
* Remove the temporary file we're using to print a job file...
*/
if (TempFile[0])
unlink(TempFile);
/*
* Exit...
*/
exit(s);
}
/*
* 'usage()' - Show program usage...
*/
static void
usage(const char *command, /* I - Command name */
const char *opt) /* I - Incorrect option, if any */
{
if (opt)
_cupsLangPrintf(stderr, _("%s: Unknown option '%c'!\n"), command, *opt);
if (!strcmp(command, "cupsfilter"))
_cupsLangPuts(stdout,
_("Usage: cupsfilter -m mime/type [ options ] filename\n"
"\n"
"Options:\n"
"\n"
" -c cupsd.conf Set cupsd.conf file to use\n"
" -j job-id[,N] Filter file N from the specified job (default is file 1)\n"
" -n copies Set number of copies\n"
" -o name=value Set option(s)\n"
" -p filename.ppd Set PPD file\n"
" -t title Set title\n"));
else
_cupsLangPuts(stdout,
_("Usage: convert [ options ]\n"
"\n"
"Options:\n"
"\n"
" -f filename Set file to be converted (otherwise stdin)\n"
" -o filename Set file to be generated (otherwise stdout)\n"
" -i mime/type Set input MIME type (otherwise auto-typed)\n"
" -j mime/type Set output MIME type (otherwise application/pdf)\n"
" -P filename.ppd Set PPD file\n"
" -a 'name=value ...' Set option(s)\n"
" -U username Set username for job\n"
" -J title Set title\n"
" -c copies Set number of copies\n"
" -u Remove the PPD file when finished\n"
" -D Remove the input file when finished\n"));
exit(1);
}
/*
* End of "$Id: cupsfilter.c 6879 2007-08-29 20:26:50Z mike $".
*/