]>
Commit | Line | Data |
---|---|---|
ac884b6a MS |
1 | // |
2 | // "$Id$" | |
3 | // | |
4 | // DDK driver interface main entry for the CUPS PPD Compiler. | |
5 | // | |
3dfe78b3 | 6 | // Copyright 2007-2008 by Apple Inc. |
ac884b6a MS |
7 | // Copyright 2002-2006 by Easy Software Products. |
8 | // | |
9 | // These coded instructions, statements, and computer programs are the | |
10 | // property of Apple Inc. and are protected by Federal copyright | |
11 | // law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
12 | // which should have been included with this file. If this file is | |
13 | // file is missing or damaged, see the license at "http://www.cups.org/". | |
14 | // | |
15 | // Contents: | |
16 | // | |
17 | // main() - Enumerate or display PPD files. | |
18 | // cat_ppd() - Display a PPD file. | |
19 | // list_ppds() - List PPDs. | |
20 | // | |
21 | ||
22 | // | |
23 | // Include necessary headers... | |
24 | // | |
25 | ||
26 | #include "ppdc.h" | |
27 | #include <cups/cups.h> | |
28 | #include <cups/dir.h> | |
29 | #include <sys/stat.h> | |
30 | #include <sys/types.h> | |
31 | ||
32 | ||
33 | // | |
34 | // Local functions... | |
35 | // | |
36 | ||
37 | static int cat_ppd(ppdcSource *src, const char *name); | |
38 | static int list_drvs(const char *pathname, const char *prefix); | |
39 | static int list_ppds(ppdcSource *src, const char *name); | |
40 | ||
41 | ||
42 | // | |
43 | // 'main()' - Enumerate or display PPD files. | |
44 | // | |
45 | ||
46 | int // O - Exit status | |
47 | main(int argc, // I - Number of command-line arguments | |
48 | char *argv[]) // I - Command-line arguments | |
49 | { | |
50 | const char *datadir; // CUPS_DATADIR | |
51 | ppdcSource *src; // PPD source file data | |
52 | char filename[1024], // Full path to .drv file(s) | |
53 | scheme[32], // URI scheme ("drv") | |
54 | userpass[256], // User/password info (unused) | |
55 | host[2], // Hostname (unused) | |
56 | resource[1024], // Resource path (/dir/to/filename.drv) | |
57 | *pc_file_name; // Filename portion of URI | |
58 | int port, // Port number (unused) | |
59 | status; // Exit status | |
60 | ||
61 | ||
62 | // Determine where CUPS has installed the data files... | |
63 | if ((datadir = getenv("CUPS_DATADIR")) == NULL) | |
64 | datadir = CUPS_DATADIR; | |
65 | ||
66 | // List all available PPDs or cat a single PPD... | |
67 | if (argc == 2 && !strcmp(argv[1], "list")) | |
68 | { | |
3dfe78b3 MS |
69 | #ifdef __APPLE__ |
70 | if (!access("/Library/Printers/PPDs.drv", 0)) | |
71 | list_drvs("/Library/Printers/PPDs.drv", "/Library/Printers/PPDs.drv"); | |
72 | #endif // __APPLE__ | |
73 | ||
ac884b6a MS |
74 | snprintf(filename, sizeof(filename), "%s/drv", datadir); |
75 | return (list_drvs(filename, "/")); | |
76 | } | |
77 | else if (argc == 3 && !strcmp(argv[1], "cat")) | |
78 | { | |
79 | httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme, sizeof(scheme), | |
80 | userpass, sizeof(userpass), host, sizeof(host), &port, | |
81 | resource, sizeof(resource)); | |
82 | ||
83 | if (strstr(resource, "../") || | |
84 | (pc_file_name = strrchr(resource, '/')) == NULL || | |
85 | pc_file_name == resource) | |
86 | { | |
87 | fprintf(stderr, "ERROR: Bad driver info URI \"%s\"!\n", argv[2]); | |
88 | return (1); | |
89 | } | |
90 | ||
91 | *pc_file_name++ = '\0'; | |
92 | ||
3dfe78b3 MS |
93 | #ifdef __APPLE__ |
94 | if (!strncmp(resource, "/Library/Printers/PPDs.drv/", 27)) | |
95 | strlcpy(filename, resource, sizeof(filename)); | |
96 | else | |
97 | #endif // __APPLE__ | |
98 | ||
ac884b6a MS |
99 | snprintf(filename, sizeof(filename), "%s/drv%s", datadir, resource); |
100 | ||
101 | src = new ppdcSource(filename); | |
102 | ||
103 | status = cat_ppd(src, pc_file_name); | |
104 | ||
105 | delete src; | |
106 | ||
107 | return (status); | |
108 | } | |
109 | ||
110 | fprintf(stderr, "ERROR: Usage: %s cat URI\n", argv[0]); | |
111 | fprintf(stderr, "ERROR: Usage: %s list\n", argv[0]); | |
112 | ||
113 | return (1); | |
114 | } | |
115 | ||
116 | ||
117 | // | |
118 | // 'cat_ppd()' - Display a PPD file. | |
119 | // | |
120 | ||
121 | static int // O - Exit status | |
122 | cat_ppd(ppdcSource *src, // I - Driver info file | |
123 | const char *name) // I - PC filename | |
124 | { | |
125 | ppdcDriver *d; // Current driver | |
126 | cups_file_t *out; // Stdout via CUPS file API | |
127 | ||
128 | ||
129 | for (d = (ppdcDriver *)src->drivers->first(); | |
130 | d; | |
131 | d = (ppdcDriver *)src->drivers->next()) | |
132 | if (!strcmp(name, d->pc_file_name->value)) | |
133 | { | |
134 | out = cupsFileStdout(); | |
135 | ||
136 | d->write_ppd_file(out, NULL, NULL, src, PPDC_LFONLY); | |
137 | cupsFileClose(out); | |
138 | return (0); | |
139 | } | |
140 | ||
141 | return (1); | |
142 | } | |
143 | ||
144 | ||
145 | // | |
146 | // 'list_drvs()' - List all drv files in the given path... | |
147 | // | |
148 | ||
149 | static int // O - Exit status | |
150 | list_drvs(const char *pathname, // I - Full path to directory | |
151 | const char *prefix) // I - Prefix for directory | |
152 | { | |
153 | char *ext, // Extension on file | |
154 | filename[1024], // Full path to .drv file(s) | |
155 | newprefix[1024]; // New prefix for directory | |
156 | cups_dir_t *dir; // Current directory | |
157 | cups_dentry_t *dent; // Current directory entry | |
158 | ||
159 | ||
160 | if ((dir = cupsDirOpen(pathname)) == NULL) | |
161 | return (1); | |
162 | ||
163 | while ((dent = cupsDirRead(dir)) != NULL) | |
164 | { | |
165 | // Skip "dot" files... | |
166 | if (dent->filename[0] == '.') | |
167 | continue; | |
168 | ||
169 | // See if this is a file or directory... | |
170 | snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename); | |
171 | ||
172 | if (S_ISDIR(dent->fileinfo.st_mode)) | |
173 | { | |
174 | // Descend into the subdirectory... | |
175 | snprintf(newprefix, sizeof(newprefix), "%s%s/", prefix, dent->filename); | |
176 | ||
177 | if (list_drvs(filename, newprefix)) | |
178 | { | |
179 | cupsDirClose(dir); | |
180 | return (1); | |
181 | } | |
182 | } | |
183 | else if ((ext = strrchr(dent->filename, '.')) != NULL && | |
184 | (!strcmp(ext, ".drv") || !strcmp(ext, ".drv.gz"))) | |
185 | { | |
186 | // List the PPDs in this driver info file... | |
187 | ppdcSource *src = new ppdcSource(filename); | |
188 | // Driver info file | |
189 | ||
190 | snprintf(newprefix, sizeof(newprefix), "%s%s", prefix, dent->filename); | |
191 | list_ppds(src, newprefix); | |
192 | delete src; | |
193 | } | |
194 | } | |
195 | ||
196 | cupsDirClose(dir); | |
197 | ||
198 | return (0); | |
199 | } | |
200 | ||
201 | ||
202 | // | |
203 | // 'list_ppds()' - List PPDs in a driver info file. | |
204 | // | |
205 | ||
206 | static int // O - Exit status | |
207 | list_ppds(ppdcSource *src, // I - Driver info file | |
208 | const char *name) // I - Name of driver info file | |
209 | { | |
210 | ppdcDriver *d; // Current driver | |
211 | ppdcAttr *attr; // 1284DeviceID attribute | |
212 | char uri[1024]; // Driver URI | |
213 | ||
214 | ||
215 | for (d = (ppdcDriver *)src->drivers->first(); | |
216 | d; | |
217 | d = (ppdcDriver *)src->drivers->next()) | |
218 | { | |
219 | httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "drv", "", "", 0, | |
220 | "%s/%s", name, d->pc_file_name->value); | |
221 | ||
222 | attr = d->find_attr("1284DeviceID", NULL); | |
223 | ||
224 | printf("\"%s\" en \"%s\" \"%s\" \"%s\"\n", uri, d->manufacturer->value, | |
225 | d->model_name->value, attr ? attr->value->value : ""); | |
226 | } | |
227 | ||
228 | return (0); | |
229 | } | |
230 | ||
231 | ||
232 | ||
233 | ||
234 | #if 0 | |
235 | ||
236 | ||
237 | ||
238 | // Scan the command-line... | |
239 | catalog = NULL; | |
240 | outdir = "ppd"; | |
241 | src = 0; | |
242 | verbose = 0; | |
243 | locales = NULL; | |
244 | comp = PPDC_NO_COMPRESSION; | |
245 | le = PPDC_LFONLY; | |
246 | ||
247 | for (i = 1; i < argc; i ++) | |
248 | if (argv[i][0] == '-') | |
249 | { | |
250 | for (opt = argv[i] + 1; *opt; opt ++) | |
251 | switch (*opt) | |
252 | { | |
253 | case 'c' : // Message catalog... | |
254 | i ++; | |
255 | if (i >= argc) | |
256 | usage(); | |
257 | ||
258 | if (verbose > 1) | |
259 | printf("ppdc: Loading messages from \"%s\"...\n", argv[i]); | |
260 | ||
261 | if (!catalog) | |
262 | catalog = new ppdcCatalog("en"); | |
263 | ||
264 | if (catalog->load_messages(argv[i])) | |
265 | { | |
266 | fprintf(stderr, | |
267 | "ppdc: Unable to load localization file \"%s\" - %s\n", | |
268 | argv[i], strerror(errno)); | |
269 | return (1); | |
270 | } | |
271 | break; | |
272 | ||
273 | case 'd' : // Output directory... | |
274 | i ++; | |
275 | if (i >= argc) | |
276 | usage(); | |
277 | ||
278 | if (verbose > 1) | |
279 | printf("ppdc: Writing PPD files to directory \"%s\"...\n", | |
280 | argv[i]); | |
281 | ||
282 | outdir = argv[i]; | |
283 | break; | |
284 | ||
285 | case 'l' : // Language(s)... | |
286 | i ++; | |
287 | if (i >= argc) | |
288 | usage(); | |
289 | ||
290 | if (strchr(argv[i], ',')) | |
291 | { | |
292 | // Comma-delimited list of languages... | |
293 | char temp[1024], // Copy of language list | |
294 | *start, // Start of current locale name | |
295 | *end; // End of current locale name | |
296 | ||
297 | ||
298 | locales = new ppdcArray(); | |
299 | ||
300 | strlcpy(temp, argv[i], sizeof(temp)); | |
301 | for (start = temp; *start; start = end) | |
302 | { | |
303 | if ((end = strchr(start, ',')) != NULL) | |
304 | *end++ = '\0'; | |
305 | else | |
306 | end = start + strlen(start); | |
307 | ||
308 | if (end > start) | |
309 | locales->add(new ppdcString(start)); | |
310 | } | |
311 | } | |
312 | else | |
313 | { | |
314 | if (verbose > 1) | |
315 | printf("ppdc: Loading messages for locale \"%s\"...\n", | |
316 | argv[i]); | |
317 | ||
318 | if (catalog) | |
319 | delete catalog; | |
320 | ||
321 | catalog = new ppdcCatalog(argv[i]); | |
322 | ||
323 | if (catalog->messages->count == 0) | |
324 | { | |
325 | fprintf(stderr, | |
326 | "ppdc: Unable to find localization for \"%s\" - %s\n", | |
327 | argv[i], strerror(errno)); | |
328 | return (1); | |
329 | } | |
330 | } | |
331 | break; | |
332 | ||
333 | case 'I' : // Include directory... | |
334 | i ++; | |
335 | if (i >= argc) | |
336 | usage(); | |
337 | ||
338 | if (verbose > 1) | |
339 | printf("ppdc: Adding include directory \"%s\"...\n", argv[i]); | |
340 | ||
341 | ppdcSource::add_include(argv[i]); | |
342 | break; | |
343 | ||
344 | case 'v' : // Be verbose... | |
345 | verbose ++; | |
346 | break; | |
347 | ||
348 | case 'z' : // Compress files... | |
349 | comp = PPDC_GZIP_COMPRESSION; | |
350 | break; | |
351 | ||
352 | case '-' : // --option | |
353 | if (!strcmp(opt, "-lf")) | |
354 | { | |
355 | le = PPDC_LFONLY; | |
356 | opt += strlen(opt) - 1; | |
357 | break; | |
358 | } | |
359 | else if (!strcmp(opt, "-cr")) | |
360 | { | |
361 | le = PPDC_CRONLY; | |
362 | opt += strlen(opt) - 1; | |
363 | break; | |
364 | } | |
365 | else if (!strcmp(opt, "-crlf")) | |
366 | { | |
367 | le = PPDC_CRLF; | |
368 | opt += strlen(opt) - 1; | |
369 | break; | |
370 | } | |
371 | ||
372 | default : // Unknown | |
373 | usage(); | |
374 | break; | |
375 | } | |
376 | } | |
377 | else | |
378 | { | |
379 | // Open and load the driver info file... | |
380 | if (verbose > 1) | |
381 | printf("ppdc: Loading driver information file \"%s\"...\n", argv[i]); | |
382 | ||
383 | src = new ppdcSource(argv[i]); | |
384 | ||
385 | // Create the output directory... | |
386 | if (mkdir(outdir, 0777)) | |
387 | { | |
388 | if (errno != EEXIST) | |
389 | { | |
390 | fprintf(stderr, "ppdc: Unable to create output directory %s: %s\n", | |
391 | outdir, strerror(errno)); | |
392 | return (1); | |
393 | } | |
394 | } | |
395 | ||
396 | // Write PPD files... | |
397 | for (d = (ppdcDriver *)src->drivers->first(); | |
398 | d; | |
399 | d = (ppdcDriver *)src->drivers->next()) | |
400 | { | |
401 | // Write the PPD file for this driver... | |
402 | for (j = 0; d->pc_file_name->value[j]; j ++) | |
403 | pcfilename[j] = tolower(d->pc_file_name->value[j]); | |
404 | ||
405 | pcfilename[j] = '\0'; | |
406 | ||
407 | if (comp == PPDC_GZIP_COMPRESSION) | |
408 | snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename); | |
409 | else | |
410 | snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename); | |
411 | ||
412 | if (verbose) | |
413 | printf("ppdc: Writing %s...\n", filename); | |
414 | ||
415 | if (d->write_ppd_file(filename, catalog, locales, src, le, comp)) | |
416 | return (1); | |
417 | } | |
418 | ||
419 | // Delete the printer driver information... | |
420 | delete src; | |
421 | } | |
422 | ||
423 | if (catalog) | |
424 | delete catalog; | |
425 | ||
426 | // If no drivers have been loaded, display the program usage message. | |
427 | if (!src) | |
428 | usage(); | |
429 | ||
430 | // Return with no errors. | |
431 | return (0); | |
432 | } | |
433 | #endif // 0 | |
434 | ||
435 | ||
436 | // | |
437 | // End of "$Id$". | |
438 | // |