4 * PostScript command filter for CUPS.
6 * Copyright 2008-2011 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * main() - Process a CUPS command file.
18 * auto_configure() - Automatically configure the printer using
19 * PostScript query commands and/or SNMP lookups.
20 * begin_ps() - Send the standard PostScript prolog.
21 * end_ps() - Send the standard PostScript trailer.
22 * print_self_test_page() - Print a self-test page.
23 * report_levels() - Report supply levels.
27 * Include necessary headers...
30 #include <cups/cups-private.h>
32 #include <cups/sidechannel.h>
39 static void auto_configure(ppd_file_t
*ppd
, const char *user
);
40 static void begin_ps(ppd_file_t
*ppd
, const char *user
);
41 static void end_ps(ppd_file_t
*ppd
);
42 static void print_self_test_page(ppd_file_t
*ppd
, const char *user
);
43 static void report_levels(ppd_file_t
*ppd
, const char *user
);
47 * 'main()' - Process a CUPS command file.
50 int /* O - Exit status */
51 main(int argc
, /* I - Number of command-line arguments */
52 char *argv
[]) /* I - Command-line arguments */
54 cups_file_t
*fp
; /* Command file */
55 char line
[1024], /* Line from file */
56 *value
; /* Value on line */
57 int linenum
; /* Line number in file */
58 ppd_file_t
*ppd
; /* PPD file */
62 * Check for valid arguments...
65 if (argc
< 6 || argc
> 7)
68 * We don't have the correct number of arguments; write an error message
72 _cupsLangPrintf(stderr
,
73 _("Usage: %s job-id user title copies options file"),
79 * Open the PPD file...
82 if ((ppd
= ppdOpenFile(getenv("PPD"))) == NULL
)
84 fputs("ERROR: Unable to open PPD file!\n", stderr
);
89 * Open the command file as needed...
94 if ((fp
= cupsFileOpen(argv
[6], "r")) == NULL
)
96 perror("ERROR: Unable to open command file - ");
101 fp
= cupsFileStdin();
104 * Read the commands from the file and send the appropriate commands...
109 while (cupsFileGetConf(fp
, line
, sizeof(line
), &value
, &linenum
))
112 * Parse the command...
115 if (!strcasecmp(line
, "AutoConfigure"))
116 auto_configure(ppd
, argv
[2]);
117 else if (!strcasecmp(line
, "PrintSelfTestPage"))
118 print_self_test_page(ppd
, argv
[2]);
119 else if (!strcasecmp(line
, "ReportLevels"))
120 report_levels(ppd
, argv
[2]);
122 fprintf(stderr
, "ERROR: Invalid printer command \"%s\"!\n", line
);
130 * 'auto_configure()' - Automatically configure the printer using PostScript
131 * query commands and/or SNMP lookups.
135 auto_configure(ppd_file_t
*ppd
, /* I - PPD file */
136 const char *user
) /* I - Printing user */
138 ppd_option_t
*option
; /* Current option in PPD */
139 ppd_attr_t
*attr
; /* Query command attribute */
140 char buffer
[1024], /* String buffer */
141 *bufptr
; /* Pointer into buffer */
142 ssize_t bytes
; /* Number of bytes read */
143 int datalen
; /* Side-channel data length */
147 * See if the backend supports bidirectional I/O...
151 if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI
, buffer
, &datalen
,
152 30.0) != CUPS_SC_STATUS_OK
||
153 buffer
[0] != CUPS_SC_BIDI_SUPPORTED
)
155 fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
156 "bidirectional I/O available!\n", stderr
);
161 * Put the printer in PostScript mode...
168 * Wait for the printer to become connected...
176 while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED
, buffer
, &datalen
,
177 5.0) == CUPS_SC_STATUS_OK
&& !buffer
[0]);
180 * Then loop through every option in the PPD file and ask for the current
184 fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr
);
186 for (option
= ppdFirstOption(ppd
); option
; option
= ppdNextOption(ppd
))
189 * See if we have a query command for this option...
192 snprintf(buffer
, sizeof(buffer
), "?%s", option
->keyword
);
194 if ((attr
= ppdFindAttr(ppd
, buffer
, NULL
)) == NULL
|| !attr
->value
)
196 fprintf(stderr
, "DEBUG: Skipping %s option...\n", option
->keyword
);
201 * Send the query code to the printer...
204 fprintf(stderr
, "DEBUG: Querying %s...\n", option
->keyword
);
205 fputs(attr
->value
, stdout
);
209 cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT
, buffer
, &datalen
, 5.0);
212 * Read the response data...
215 while ((bytes
= cupsBackChannelRead(buffer
, sizeof(buffer
) - 1, 90.0)) > 0)
218 * Trim whitespace from both ends...
221 buffer
[bytes
] = '\0';
223 for (bufptr
= buffer
+ bytes
- 1; bufptr
>= buffer
; bufptr
--)
224 if (isspace(*bufptr
& 255))
229 for (bufptr
= buffer
; isspace(*bufptr
& 255); bufptr
++);
231 fprintf(stderr
, "DEBUG: Got \"%s\" (%d bytes)\n", bufptr
, (int)bytes
);
234 * Skip blank lines...
241 * Verify the result is a valid option choice...
244 if (!ppdFindChoice(option
, bufptr
))
248 * Write out the result and move on to the next option...
251 fprintf(stderr
, "DEBUG: Default%s=%s\n", option
->keyword
, bufptr
);
252 fprintf(stderr
, "PPD: Default%s=%s\n", option
->keyword
, bufptr
);
266 * 'begin_ps()' - Send the standard PostScript prolog.
270 begin_ps(ppd_file_t
*ppd
, /* I - PPD file */
271 const char *user
) /* I - Username */
277 fputs(ppd
->jcl_begin
, stdout
);
278 fputs(ppd
->jcl_ps
, stdout
);
282 puts("userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n");
288 * 'end_ps()' - Send the standard PostScript trailer.
292 end_ps(ppd_file_t
*ppd
) /* I - PPD file */
295 fputs(ppd
->jcl_end
, stdout
);
304 * 'print_self_test_page()' - Print a self-test page.
308 print_self_test_page(ppd_file_t
*ppd
, /* I - PPD file */
309 const char *user
) /* I - Printing user */
312 * Put the printer in PostScript mode...
318 * Send a simple file the draws a box around the imageable area and shows
319 * the product/interpreter information...
322 puts("% You are using the wrong driver for your printer!\n"
325 "initclip newpath clippath gsave stroke grestore pathbbox\n"
326 "exch pop exch pop exch 9 add exch 9 sub moveto\n"
327 "/Courier findfont 12 scalefont setfont\n"
328 "0 -12 rmoveto gsave product show grestore\n"
329 "0 -12 rmoveto gsave version show ( ) show revision 20 string cvs show "
331 "0 -12 rmoveto gsave serialnumber 20 string cvs show grestore\n"
343 * 'report_levels()' - Report supply levels.
347 report_levels(ppd_file_t
*ppd
, /* I - PPD file */
348 const char *user
) /* I - Printing user */
351 * Put the printer in PostScript mode...
357 * Don't bother sending any additional PostScript commands, since we just
358 * want the backend to have enough time to collect the supply info.