#include <cups/cups-private.h>
#include <cups/file-private.h>
#include <cups/ppd-private.h>
#include "mime.h"
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#if defined(__APPLE__)
# include <libgen.h>
#endif
static char *DataDir = NULL;
static char *FontPath = NULL;
static mime_filter_t GZIPFilter =
{
NULL,
NULL,
0,
"gziptoany"
};
static char *Path = NULL;
static char *ServerBin = NULL;
static char *ServerRoot = NULL;
static char *RIPCache = NULL;
static char TempFile[1024] = "";
static void add_printer_filter(const char *command, mime_t *mime,
mime_type_t *printer_type,
const char *filter);
static mime_type_t *add_printer_filters(const char *command,
mime_t *mime, const char *printer,
const char *ppdfile,
mime_type_t **prefilter_type);
static void check_cb(void *context, _cups_fc_result_t result,
const char *message);
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(mime_type_t *srctype,
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);
int
main(int argc,
char *argv[])
{
int i;
const char *command,
*opt,
*printer;
mime_type_t *printer_type,
*prefilter_type;
char *srctype,
*dsttype,
super[MIME_MAX_SUPER],
type[MIME_MAX_TYPE];
int compression;
int cost;
mime_t *mime;
char mimedir[1024];
char *infile,
*outfile;
char cupsdconf[1024];
const char *server_root;
mime_type_t *src,
*dst;
cups_array_t *filters;
int num_options;
cups_option_t *options;
const char *ppdfile;
const char *title,
*user;
int all_filters,
removeppd,
removeinfile;
int status;
if ((command = strrchr(argv[0], '/')) != NULL)
command ++;
else
command = argv[0];
printer = !strcmp(command, "convert") ? "tofile" : "cupsfilter";
mime = NULL;
srctype = NULL;
compression = 0;
dsttype = "application/pdf";
infile = NULL;
outfile = NULL;
num_options = 0;
options = NULL;
ppdfile = NULL;
title = NULL;
user = cupsUser();
all_filters = 0;
removeppd = 0;
removeinfile = 0;
if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
server_root = CUPS_SERVERROOT;
snprintf(cupsdconf, sizeof(cupsdconf), "%s/cupsd.conf", server_root);
_cupsSetLocale(argv);
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
{
for (opt = argv[i] + 1; *opt; opt ++)
switch (*opt)
{
case '-' :
i ++;
if (i < argc && !infile)
infile = argv[i];
else
usage(command, opt);
break;
case 'a' :
i ++;
if (i < argc)
num_options = cupsParseOptions(argv[i], num_options, &options);
else
usage(command, opt);
break;
case 'c' :
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' :
i ++;
if (i < argc)
printer = argv[i];
else
usage(command, opt);
break;
case 'D' :
removeinfile = 1;
break;
case 'e' :
all_filters = 1;
break;
case 'f' :
i ++;
if (i < argc && !infile)
infile = argv[i];
else
usage(command, opt);
break;
case 'i' :
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' :
if (strcmp(command, "convert"))
{
i ++;
if (i < argc)
{
get_job_file(argv[i]);
infile = TempFile;
}
else
usage(command, opt);
break;
}
case 'm' :
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' :
i ++;
if (i < argc)
num_options = cupsAddOption("copies", argv[i], num_options,
&options);
else
usage(command, opt);
break;
case 'o' :
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' :
case 'P' :
i ++;
if (i < argc)
ppdfile = argv[i];
else
usage(command, opt);
break;
case 't' :
case 'J' :
i ++;
if (i < argc)
title = argv[i];
else
usage(command, opt);
break;
case 'u' :
removeppd = 1;
break;
case 'U' :
i ++;
if (i < argc)
user = argv[i];
else
usage(command, opt);
break;
default :
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."));
usage(command, NULL);
}
}
else
{
_cupsLangPuts(stderr,
_("cupsfilter: Only one filename can be specified."));
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;
}
if (read_cupsd_conf(cupsdconf))
return (1);
snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
mime = mimeLoadTypes(NULL, mimedir);
mime = mimeLoadTypes(mime, ServerRoot);
mime = mimeLoadFilters(mime, mimedir, Path);
mime = mimeLoadFilters(mime, ServerRoot, Path);
if (!mime)
{
_cupsLangPrintf(stderr,
_("%s: Unable to read MIME database from \"%s\" or "
"\"%s\"."),
command, mimedir, ServerRoot);
return (1);
}
prefilter_type = NULL;
if (all_filters)
printer_type = add_printer_filters(command, mime, printer, ppdfile,
&prefilter_type);
else
printer_type = mimeType(mime, "application", "vnd.cups-postscript");
if (srctype)
{
sscanf(srctype, "%15[^/]/%255s", super, type);
if ((src = mimeType(mime, super, type)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unknown source MIME type %s/%s."),
command, super, type);
return (1);
}
}
else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unable to determine MIME type of \"%s\"."),
command, infile);
return (1);
}
sscanf(dsttype, "%15[^/]/%255s", super, type);
if (!_cups_strcasecmp(super, "printer"))
dst = printer_type;
else if ((dst = mimeType(mime, super, type)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: Unknown destination MIME type %s/%s."),
command, super, type);
return (1);
}
if (src == dst)
{
filters = cupsArrayNew(NULL, NULL);
cupsArrayAdd(filters, &GZIPFilter);
GZIPFilter.src = src;
GZIPFilter.dst = dst;
}
else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
{
_cupsLangPrintf(stderr,
_("%s: No filter to convert from %s/%s to %s/%s."),
command, src->super, src->type, dst->super, dst->type);
return (1);
}
else if (compression)
cupsArrayInsert(filters, &GZIPFilter);
if (prefilter_type)
{
mime_filter_t *filter,
*prefilter;
cups_array_t *prefilters = cupsArrayNew(NULL, NULL);
for (filter = (mime_filter_t *)cupsArrayFirst(filters);
filter;
filter = (mime_filter_t *)cupsArrayNext(filters))
{
if ((prefilter = mimeFilterLookup(mime, filter->src,
prefilter_type)) != NULL)
cupsArrayAdd(prefilters, prefilter);
cupsArrayAdd(prefilters, filter);
}
cupsArrayDelete(filters);
filters = prefilters;
}
status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user,
title, num_options, options);
if (TempFile[0])
unlink(TempFile);
if (removeppd && ppdfile)
unlink(ppdfile);
if (removeinfile && infile)
unlink(infile);
return (status);
}
static void
add_printer_filter(
const char *command,
mime_t *mime,
mime_type_t *filtertype,
const char *filter)
{
char super[MIME_MAX_SUPER],
type[MIME_MAX_TYPE],
dsuper[MIME_MAX_SUPER],
dtype[MIME_MAX_TYPE],
dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
program[1024];
int cost;
size_t maxsize = 0;
mime_type_t *temptype,
*desttype;
mime_filter_t *filterptr;
if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
super, type, dsuper, dtype, &cost, program) == 6)
{
snprintf(dest, sizeof(dest), "%s/%s/%s", filtertype->type, dsuper, dtype);
if ((desttype = mimeType(mime, "printer", dest)) == NULL)
desttype = mimeAddType(mime, "printer", dest);
}
else
{
if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
program) == 4)
{
desttype = filtertype;
}
else
{
_cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"."), command,
filter);
return;
}
}
if (!strncmp(program, "maxsize(", 8))
{
char *ptr;
maxsize = strtoll(program + 8, &ptr, 10);
if (*ptr != ')')
{
printf("testmime: Invalid filter string \"%s\".\n", filter);
return;
}
ptr ++;
while (_cups_isspace(*ptr))
ptr ++;
_cups_strcpy(program, ptr);
}
if (strcmp(program, "-"))
{
char filename[1024];
if (program[0] == '/')
strlcpy(filename, program, sizeof(filename));
else
snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !geteuid(), check_cb,
(void *)command))
return;
}
for (temptype = mimeFirstType(mime);
temptype;
temptype = mimeNextType(mime))
if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
!_cups_strcasecmp(temptype->super, super)) &&
(type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
{
if (desttype != filtertype)
{
filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);
if (!mimeFilterLookup(mime, desttype, filtertype))
mimeAddFilter(mime, desttype, filtertype, 0, "-");
}
else
filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);
if (filterptr)
filterptr->maxsize = maxsize;
}
}
static mime_type_t *
add_printer_filters(
const char *command,
mime_t *mime,
const char *printer,
const char *ppdfile,
mime_type_t **prefilter_type)
{
ppd_file_t *ppd;
_ppd_cache_t *pc;
const char *value;
mime_type_t *printer_type;
if ((ppd = ppdOpenFile(ppdfile)) == NULL)
{
ppd_status_t status;
int linenum;
status = ppdLastError(&linenum);
_cupsLangPrintf(stderr, _("%s: Unable to open PPD file: %s on line %d."),
command, ppdErrorString(status), linenum);
return (NULL);
}
pc = _ppdCacheCreateWithPPD(ppd);
if (!pc)
return (NULL);
printer_type = mimeAddType(mime, "printer", printer);
*prefilter_type = NULL;
if (pc->filters)
{
for (value = (const char *)cupsArrayFirst(pc->filters);
value;
value = (const char *)cupsArrayNext(pc->filters))
add_printer_filter(command, mime, printer_type, value);
}
else
{
add_printer_filter(command, mime, printer_type,
"application/vnd.cups-raw 0 -");
add_printer_filter(command, mime, printer_type,
"application/vnd.cups-postscript 0 -");
}
if (pc->prefilters)
{
*prefilter_type = mimeAddType(mime, "prefilter", printer);
for (value = (const char *)cupsArrayFirst(pc->prefilters);
value;
value = (const char *)cupsArrayNext(pc->prefilters))
add_printer_filter(command, mime, *prefilter_type, value);
}
return (printer_type);
}
static void
check_cb(void *context,
_cups_fc_result_t result,
const char *message)
{
(void)result;
_cupsLangPrintf(stderr, _("%s: %s"), (char *)context, message);
}
static int
compare_pids(mime_filter_t *a,
mime_filter_t *b)
{
return (a->cost - b->cost);
}
static char *
escape_options(
int num_options,
cups_option_t *options)
{
int i;
cups_option_t *option;
int bytes;
char *s,
*sptr,
*vptr;
for (i = num_options, option = options, bytes = 1; i > 0; i --, option ++)
bytes += 2 * (strlen(option->name) + strlen(option->value)) + 2;
if ((s = malloc(bytes)) == NULL)
return (NULL);
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);
}
static int
exec_filter(const char *filter,
char **argv,
char **envp,
int infd,
int outfd)
{
int pid,
fd;
#if defined(__APPLE__)
char processPath[1024],
linkpath[1024];
int linkbytes;
if ((linkbytes = readlink(filter, linkpath, sizeof(linkpath) - 1)) > 0)
{
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;
#endif
if ((pid = fork()) == 0)
{
if (infd != 0)
{
if (infd < 0)
infd = open("/dev/null", O_RDONLY);
if (infd > 0)
{
dup2(infd, 0);
close(infd);
}
}
if (outfd != 1)
{
if (outfd < 0)
outfd = open("/dev/null", O_WRONLY);
if (outfd > 1)
{
dup2(outfd, 1);
close(outfd);
}
}
if ((fd = open("/dev/null", O_RDWR)) > 3)
{
dup2(fd, 3);
close(fd);
}
fcntl(3, F_SETFL, O_NDELAY);
if ((fd = open("/dev/null", O_RDWR)) > 4)
{
dup2(fd, 4);
close(fd);
}
fcntl(4, F_SETFL, O_NDELAY);
execve(filter, argv, envp);
perror(filter);
exit(errno);
}
return (pid);
}
static int
exec_filters(mime_type_t *srctype,
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)
{
int i;
const char *argv[8],
*envp[15],
*temp;
char *optstr,
content_type[1024],
cups_datadir[1024],
cups_fontpath[1024],
cups_serverbin[1024],
cups_serverroot[1024],
lang[1024],
path[1024],
ppd[1024],
printer_info[255],
printer_location[255],
printer_name[255],
rip_max_cache[1024],
userenv[1024],
program[1024];
mime_filter_t *filter,
*next;
int current,
filterfds[2][2],
pid,
status,
retval;
cups_array_t *pids;
mime_filter_t key;
cups_lang_t *language;
cups_dest_t *dest;
optstr = escape_options(num_options, options);
snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
srctype->super, srctype->type);
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
snprintf(rip_max_cache, sizeof(rip_max_cache), "RIP_MAX_CACHE=%s", RIPCache);
snprintf(userenv, sizeof(userenv), "USER=%s", user);
if (printer &&
(dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, NULL)) != NULL)
{
if ((temp = cupsGetOption("printer-info", dest->num_options,
dest->options)) != NULL)
snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", temp);
else
snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", printer);
if ((temp = cupsGetOption("printer-location", dest->num_options,
dest->options)) != NULL)
snprintf(printer_location, sizeof(printer_location),
"PRINTER_LOCATION=%s", temp);
else
strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
sizeof(printer_location));
}
else
{
snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s",
printer ? printer : "Unknown");
strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
sizeof(printer_location));
}
snprintf(printer_name, sizeof(printer_name), "PRINTER=%s",
printer ? printer : "Unknown");
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] = content_type;
envp[2] = cups_datadir;
envp[3] = cups_fontpath;
envp[4] = cups_serverbin;
envp[5] = cups_serverroot;
envp[6] = lang;
envp[7] = path;
envp[8] = ppd;
envp[9] = printer_info;
envp[10] = printer_location;
envp[11] = printer_name;
envp[12] = rip_max_cache;
envp[13] = userenv;
envp[14] = 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]);
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;
}
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]);
}
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);
}
}
cupsArrayDelete(pids);
return (retval);
}
static void
get_job_file(const char *job)
{
long jobid,
docnum;
const char *jobptr;
char uri[1024];
http_t *http;
ipp_t *request;
int tempfd;
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."), (int)jobid);
exit(1);
}
if (docnum < 1 || docnum > INT_MAX)
{
_cupsLangPrintf(stderr, _("cupsfilter: Invalid document number %d."),
(int)docnum);
exit(1);
}
if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
cupsEncryption())) == NULL)
{
_cupsLangPrintf(stderr, _("%s: Unable to connect to server."),
"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)
{
_cupsLangPrintError("ERROR", _("Unable to create temporary file"));
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"),
cupsLastErrorString());
unlink(TempFile);
exit(1);
}
}
static int
open_pipe(int *fds)
{
if (pipe(fds))
{
fds[0] = -1;
fds[1] = -1;
return (-1);
}
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);
}
static int
read_cupsd_conf(const char *filename)
{
cups_file_t *fp;
const char *temp;
char line[1024],
*ptr;
int linenum;
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, "128m");
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 (!_cups_strcasecmp(line, "DataDir"))
set_string(&DataDir, ptr);
else if (!_cups_strcasecmp(line, "FontPath"))
set_string(&FontPath, ptr);
else if (!_cups_strcasecmp(line, "RIPCache"))
set_string(&RIPCache, ptr);
else if (!_cups_strcasecmp(line, "ServerBin"))
set_string(&ServerBin, ptr);
else if (!_cups_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);
}
static void
set_string(char **s,
const char *val)
{
if (*s)
free(*s);
*s = strdup(val);
}
static void
sighandler(int s)
{
if (TempFile[0])
unlink(TempFile);
exit(s);
}
static void
usage(const char *command,
const char *opt)
{
if (opt)
_cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), command, *opt);
if (!strcmp(command, "cupsfilter"))
{
_cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] filename"));
_cupsLangPuts(stdout, _("Options:"));
_cupsLangPuts(stdout, _(" -D Remove the input file "
"when finished."));
_cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file."));
_cupsLangPuts(stdout, _(" -U username Set username for job."));
_cupsLangPuts(stdout, _(" -c cupsd.conf Set cupsd.conf file to "
"use."));
_cupsLangPuts(stdout, _(" -d printer Use the named "
"printer."));
_cupsLangPuts(stdout, _(" -e Use every filter from "
"the PPD file."));
_cupsLangPuts(stdout, _(" -i mime/type Set input MIME type "
"(otherwise auto-typed)."));
_cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the "
"specified job (default is file 1)."));
_cupsLangPuts(stdout, _(" -m mime/type Set output MIME type "
"(otherwise application/pdf)."));
_cupsLangPuts(stdout, _(" -n copies Set number of copies."));
_cupsLangPuts(stdout, _(" -o name=value Set option(s)."));
_cupsLangPuts(stdout, _(" -p filename.ppd Set PPD file."));
_cupsLangPuts(stdout, _(" -t title Set title."));
_cupsLangPuts(stdout, _(" -u Remove the PPD file "
"when finished."));
}
else
{
_cupsLangPuts(stdout, _("Usage: convert [ options ]"));
_cupsLangPuts(stdout, _("Options:"));
_cupsLangPuts(stdout, _(" -D Remove the input file "
"when finished."));
_cupsLangPuts(stdout, _(" -J title Set title."));
_cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file."));
_cupsLangPuts(stdout, _(" -U username Set username for job."));
_cupsLangPuts(stdout, _(" -a 'name=value ...' Set option(s)."));
_cupsLangPuts(stdout, _(" -c copies Set number of copies."));
_cupsLangPuts(stdout, _(" -d printer Use the named "
"printer."));
_cupsLangPuts(stdout, _(" -e Use every filter from "
"the PPD file."));
_cupsLangPuts(stdout, _(" -f filename Set file to be "
"converted (otherwise stdin)."));
_cupsLangPuts(stdout, _(" -i mime/type Set input MIME type "
"(otherwise auto-typed)."));
_cupsLangPuts(stdout, _(" -j mime/type Set output MIME type "
"(otherwise application/pdf)."));
_cupsLangPuts(stdout, _(" -o filename Set file to be "
"generated (otherwise stdout)."));
_cupsLangPuts(stdout, _(" -u Remove the PPD file "
"when finished."));
}
exit(1);
}