#include <cups/cups.h>
#include <cups/string.h>
#include <cups/sidechannel.h>
static void auto_configure(ppd_file_t *ppd, const char *user);
static void begin_ps(ppd_file_t *ppd, const char *user);
static void end_ps(ppd_file_t *ppd);
static void print_self_test_page(ppd_file_t *ppd, const char *user);
static void report_levels(ppd_file_t *ppd, const char *user);
int
main(int argc,
char *argv[])
{
cups_file_t *fp;
char line[1024],
*value;
int linenum;
ppd_file_t *ppd;
if (argc < 6 || argc > 7)
{
fputs("ERROR: commandtops job-id user title copies options [file]\n", stderr);
return (1);
}
if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL)
{
fputs("ERROR: Unable to open PPD file!\n", stderr);
return (1);
}
if (argc == 7)
{
if ((fp = cupsFileOpen(argv[6], "r")) == NULL)
{
perror("ERROR: Unable to open command file - ");
return (1);
}
}
else
fp = cupsFileStdin();
linenum = 0;
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
{
if (!strcasecmp(line, "AutoConfigure"))
auto_configure(ppd, argv[2]);
else if (!strcasecmp(line, "PrintSelfTestPage"))
print_self_test_page(ppd, argv[2]);
else if (!strcasecmp(line, "ReportLevels"))
report_levels(ppd, argv[2]);
else
fprintf(stderr, "ERROR: Invalid printer command \"%s\"!\n", line);
}
return (0);
}
static void
auto_configure(ppd_file_t *ppd,
const char *user)
{
ppd_option_t *option;
ppd_attr_t *attr;
char buffer[1024],
*bufptr;
ssize_t bytes;
int datalen;
datalen = 1;
if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer, &datalen,
30.0) != CUPS_SC_STATUS_OK ||
buffer[0] != CUPS_SC_BIDI_SUPPORTED)
{
fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
"bidirectional I/O available!\n", stderr);
return;
}
begin_ps(ppd, user);
fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr);
for (option = ppdFirstOption(ppd); option; option = ppdNextOption(ppd))
{
snprintf(buffer, sizeof(buffer), "?%s", option->keyword);
if ((attr = ppdFindAttr(ppd, buffer, NULL)) == NULL || !attr->value)
{
fprintf(stderr, "DEBUG: Skipping %s option...\n", option->keyword);
continue;
}
fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword);
fputs(attr->value, stdout);
fflush(stdout);
datalen = 0;
cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer, &datalen, 5.0);
while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 5.0)) > 0)
{
buffer[bytes] = '\0';
for (bufptr = buffer + bytes - 1; bufptr >= buffer; bufptr --)
if (isspace(*bufptr & 255))
*bufptr = '\0';
else
break;
for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++);
if (!*bufptr)
continue;
fprintf(stderr, "DEBUG: Default%s=%s\n", option->keyword, bufptr);
fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, bufptr);
break;
}
}
end_ps(ppd);
}
static void
begin_ps(ppd_file_t *ppd,
const char *user)
{
(void)user;
if (ppd->jcl_begin)
{
fputs(ppd->jcl_begin, stdout);
fputs(ppd->jcl_ps, stdout);
}
puts("%!");
puts("userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n");
fflush(stdout);
}
static void
end_ps(ppd_file_t *ppd)
{
if (ppd->jcl_end)
fputs(ppd->jcl_end, stdout);
else
putchar(0x04);
fflush(stdout);
}
static void
print_self_test_page(ppd_file_t *ppd,
const char *user)
{
begin_ps(ppd, user);
puts("% You are using the wrong driver for your printer!\n"
"0 setgray\n"
"2 setlinewidth\n"
"initclip newpath clippath gsave stroke grestore pathbbox\n"
"exch pop exch pop exch 9 add exch 9 sub moveto\n"
"/Courier findfont 12 scalefont setfont\n"
"0 -12 rmoveto gsave product show grestore\n"
"0 -12 rmoveto gsave version show ( ) show revision 20 string cvs show "
"grestore\n"
"0 -12 rmoveto gsave serialnumber 20 string cvs show grestore\n"
"showpage");
end_ps(ppd);
}
static void
report_levels(ppd_file_t *ppd,
const char *user)
{
begin_ps(ppd, user);
end_ps(ppd);
}