]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/commandtops.c
Merge CUPS 1.4svn-r7524.
[thirdparty/cups.git] / filter / commandtops.c
CommitLineData
7a14d768
MS
1/*
2 * "$Id$"
3 *
4 * PostScript command filter for CUPS.
5 *
6 * Copyright 2008 by Apple Inc.
7 *
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/".
13 *
14 *
15 * Contents:
16 *
17 */
18
19/*
20 * Include necessary headers...
21 */
22
23#include <cups/cups.h>
24#include <cups/string.h>
25#include <cups/sidechannel.h>
26
27
28/*
29 * Local functions...
30 */
31
32static void auto_configure(ppd_file_t *ppd, const char *user);
33static void print_self_test_page(ppd_file_t *ppd, const char *user);
34static void report_levels(ppd_file_t *ppd, const char *user);
35
36
37/*
38 * 'main()' - Process a CUPS command file.
39 */
40
41int /* O - Exit status */
42main(int argc, /* I - Number of command-line arguments */
43 char *argv[]) /* I - Command-line arguments */
44{
45 cups_file_t *fp; /* Command file */
46 char line[1024], /* Line from file */
47 *value; /* Value on line */
48 int linenum; /* Line number in file */
49 ppd_file_t *ppd; /* PPD file */
50
51
52 /*
53 * Check for valid arguments...
54 */
55
56 if (argc < 6 || argc > 7)
57 {
58 /*
59 * We don't have the correct number of arguments; write an error message
60 * and return.
61 */
62
63 fputs("ERROR: commandtops job-id user title copies options [file]\n", stderr);
64 return (1);
65 }
66
67 /*
68 * Open the PPD file...
69 */
70
71 if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL)
72 {
73 fputs("ERROR: Unable to open PPD file!\n", stderr);
74 return (1);
75 }
76
77 /*
78 * Open the command file as needed...
79 */
80
81 if (argc == 7)
82 {
83 if ((fp = cupsFileOpen(argv[6], "r")) == NULL)
84 {
85 perror("ERROR: Unable to open command file - ");
86 return (1);
87 }
88 }
89 else
90 fp = cupsFileStdin();
91
92 /*
93 * Read the commands from the file and send the appropriate commands...
94 */
95
96 linenum = 0;
97
98 while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
99 {
100 /*
101 * Parse the command...
102 */
103
104 if (!strcasecmp(line, "AutoConfigure"))
105 auto_configure(ppd, argv[2]);
106 else if (!strcasecmp(line, "PrintSelfTestPage"))
107 print_self_test_page(ppd, argv[2]);
108 else if (!strcasecmp(line, "ReportLevels"))
109 report_levels(ppd, argv[2]);
110 else
111 fprintf(stderr, "ERROR: Invalid printer command \"%s\"!\n", line);
112 }
113
114 return (0);
115}
116
117
118/*
119 * 'auto_configure()' - Automatically configure the printer using PostScript
120 * query commands and/or SNMP lookups.
121 */
122
123static void
124auto_configure(ppd_file_t *ppd, /* I - PPD file */
125 const char *user) /* I - Printing user */
126{
127 ppd_option_t *option; /* Current option in PPD */
128 ppd_attr_t *attr; /* Query command attribute */
129 char buffer[1024], /* String buffer */
130 *bufptr; /* Pointer into buffer */
131 ssize_t bytes; /* Number of bytes read */
132 int datalen; /* Side-channel data length */
133
134
135 /*
136 * See if the backend supports bidirectional I/O...
137 */
138
139 datalen = 1;
140 if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer, &datalen,
141 30.0) != CUPS_SC_STATUS_OK ||
142 buffer[0] != CUPS_SC_BIDI_SUPPORTED)
143 {
144 fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
145 "bidirectional I/O available!\n", stderr);
146 return;
147 }
148
149 /*
150 * Put the printer in PostScript mode...
151 */
152
153 if (ppd->jcl_begin)
154 {
155 fputs(ppd->jcl_begin, stdout);
156 fputs(ppd->jcl_ps, stdout);
157 }
158
159 puts("%!");
160 fflush(stdout);
161
162 /*
163 * Then loop through every option in the PPD file and ask for the current
164 * value...
165 */
166
167 fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr);
168
169 for (option = ppdFirstOption(ppd); option; option = ppdNextOption(ppd))
170 {
171 /*
172 * See if we have a query command for this option...
173 */
174
175 snprintf(buffer, sizeof(buffer), "?%s", option->keyword);
176
177 if ((attr = ppdFindAttr(ppd, buffer, NULL)) == NULL || !attr->value)
178 {
179 fprintf(stderr, "DEBUG: Skipping %s option...\n", option->keyword);
180 continue;
181 }
182
183 /*
184 * Send the query code to the printer...
185 */
186
187 fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword);
188 fputs(attr->value, stdout);
189 fflush(stdout);
190
191 datalen = 0;
192 cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer, &datalen, 5.0);
193
194 /*
195 * Read the response data...
196 */
197
198 while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 5.0)) > 0)
199 {
200 /*
201 * Trim whitespace from both ends...
202 */
203
204 buffer[bytes] = '\0';
205
206 for (bufptr = buffer + bytes - 1; bufptr >= buffer; bufptr --)
207 if (isspace(*bufptr & 255))
208 *bufptr = '\0';
209 else
210 break;
211
212 for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++);
213
214 /*
215 * Skip blank lines...
216 */
217
218 if (!*bufptr)
219 continue;
220
221 /*
222 * Write out the result and move on to the next option...
223 */
224
225 fprintf(stderr, "DEBUG: Default%s=%s\n", option->keyword, bufptr);
226 fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, bufptr);
227 break;
228 }
229 }
230
231 /*
232 * Finish the job...
233 */
234
235 if (ppd->jcl_begin)
236 fputs(ppd->jcl_begin, stdout);
237 else
238 putchar(0x04);
239
240 fflush(stdout);
241}
242
243
244/*
245 * 'print_self_test_page()' - Print a self-test page.
246 */
247
248static void
249print_self_test_page(ppd_file_t *ppd, /* I - PPD file */
250 const char *user) /* I - Printing user */
251{
252 /*
253 * Put the printer in PostScript mode...
254 */
255
256 if (ppd->jcl_begin)
257 {
258 fputs(ppd->jcl_begin, stdout);
259 fputs(ppd->jcl_ps, stdout);
260 }
261
262 puts("%!");
263
264 /*
265 * Send a simple file the draws a box around the imageable area and shows
266 * the product/interpreter information...
267 */
268
269 puts("% You are using the wrong driver for your printer!\n"
270 "0 setgray\n"
271 "2 setlinewidth\n"
272 "initclip newpath clippath gsave stroke grestore pathbbox\n"
273 "exch pop exch pop exch 9 add exch 9 sub moveto\n"
274 "/Courier findfont 12 scalefont setfont\n"
275 "0 -12 rmoveto gsave product show grestore\n"
276 "0 -12 rmoveto gsave version show ( ) show revision 20 string cvs show "
277 "grestore\n"
278 "0 -12 rmoveto gsave serialnumber 20 string cvs show grestore\n"
279 "showpage");
280
281 /*
282 * Finish the job...
283 */
284
285 if (ppd->jcl_begin)
286 fputs(ppd->jcl_begin, stdout);
287 else
288 putchar(0x04);
289
290 fflush(stdout);
291}
292
293
294/*
295 * 'report_levels()' - Report supply levels.
296 */
297
298static void
299report_levels(ppd_file_t *ppd, /* I - PPD file */
300 const char *user) /* I - Printing user */
301{
302 /*
303 * Put the printer in PostScript mode...
304 */
305
306 if (ppd->jcl_begin)
307 {
308 fputs(ppd->jcl_begin, stdout);
309 fputs(ppd->jcl_ps, stdout);
310 }
311
312 puts("%!");
313
314 /*
315 * Finish the job...
316 */
317
318 if (ppd->jcl_begin)
319 fputs(ppd->jcl_begin, stdout);
320 else
321 putchar(0x04);
322
323 fflush(stdout);
324}
325
326
327/*
328 * End of "$Id$".
329 */