]> git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/drv.cxx
Merge CUPS 1.4svn-r7319.
[thirdparty/cups.git] / ppdc / drv.cxx
1 //
2 // "$Id$"
3 //
4 // DDK driver interface main entry for the CUPS PPD Compiler.
5 //
6 // Copyright 2007 by Apple Inc.
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 {
69 snprintf(filename, sizeof(filename), "%s/drv", datadir);
70 return (list_drvs(filename, "/"));
71 }
72 else if (argc == 3 && !strcmp(argv[1], "cat"))
73 {
74 httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme, sizeof(scheme),
75 userpass, sizeof(userpass), host, sizeof(host), &port,
76 resource, sizeof(resource));
77
78 if (strstr(resource, "../") ||
79 (pc_file_name = strrchr(resource, '/')) == NULL ||
80 pc_file_name == resource)
81 {
82 fprintf(stderr, "ERROR: Bad driver info URI \"%s\"!\n", argv[2]);
83 return (1);
84 }
85
86 *pc_file_name++ = '\0';
87
88 snprintf(filename, sizeof(filename), "%s/drv%s", datadir, resource);
89
90 src = new ppdcSource(filename);
91
92 status = cat_ppd(src, pc_file_name);
93
94 delete src;
95
96 return (status);
97 }
98
99 fprintf(stderr, "ERROR: Usage: %s cat URI\n", argv[0]);
100 fprintf(stderr, "ERROR: Usage: %s list\n", argv[0]);
101
102 return (1);
103 }
104
105
106 //
107 // 'cat_ppd()' - Display a PPD file.
108 //
109
110 static int // O - Exit status
111 cat_ppd(ppdcSource *src, // I - Driver info file
112 const char *name) // I - PC filename
113 {
114 ppdcDriver *d; // Current driver
115 cups_file_t *out; // Stdout via CUPS file API
116
117
118 for (d = (ppdcDriver *)src->drivers->first();
119 d;
120 d = (ppdcDriver *)src->drivers->next())
121 if (!strcmp(name, d->pc_file_name->value))
122 {
123 out = cupsFileStdout();
124
125 d->write_ppd_file(out, NULL, NULL, src, PPDC_LFONLY);
126 cupsFileClose(out);
127 return (0);
128 }
129
130 return (1);
131 }
132
133
134 //
135 // 'list_drvs()' - List all drv files in the given path...
136 //
137
138 static int // O - Exit status
139 list_drvs(const char *pathname, // I - Full path to directory
140 const char *prefix) // I - Prefix for directory
141 {
142 char *ext, // Extension on file
143 filename[1024], // Full path to .drv file(s)
144 newprefix[1024]; // New prefix for directory
145 cups_dir_t *dir; // Current directory
146 cups_dentry_t *dent; // Current directory entry
147
148
149 if ((dir = cupsDirOpen(pathname)) == NULL)
150 return (1);
151
152 while ((dent = cupsDirRead(dir)) != NULL)
153 {
154 // Skip "dot" files...
155 if (dent->filename[0] == '.')
156 continue;
157
158 // See if this is a file or directory...
159 snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
160
161 if (S_ISDIR(dent->fileinfo.st_mode))
162 {
163 // Descend into the subdirectory...
164 snprintf(newprefix, sizeof(newprefix), "%s%s/", prefix, dent->filename);
165
166 if (list_drvs(filename, newprefix))
167 {
168 cupsDirClose(dir);
169 return (1);
170 }
171 }
172 else if ((ext = strrchr(dent->filename, '.')) != NULL &&
173 (!strcmp(ext, ".drv") || !strcmp(ext, ".drv.gz")))
174 {
175 // List the PPDs in this driver info file...
176 ppdcSource *src = new ppdcSource(filename);
177 // Driver info file
178
179 snprintf(newprefix, sizeof(newprefix), "%s%s", prefix, dent->filename);
180 list_ppds(src, newprefix);
181 delete src;
182 }
183 }
184
185 cupsDirClose(dir);
186
187 return (0);
188 }
189
190
191 //
192 // 'list_ppds()' - List PPDs in a driver info file.
193 //
194
195 static int // O - Exit status
196 list_ppds(ppdcSource *src, // I - Driver info file
197 const char *name) // I - Name of driver info file
198 {
199 ppdcDriver *d; // Current driver
200 ppdcAttr *attr; // 1284DeviceID attribute
201 char uri[1024]; // Driver URI
202
203
204 for (d = (ppdcDriver *)src->drivers->first();
205 d;
206 d = (ppdcDriver *)src->drivers->next())
207 {
208 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "drv", "", "", 0,
209 "%s/%s", name, d->pc_file_name->value);
210
211 attr = d->find_attr("1284DeviceID", NULL);
212
213 printf("\"%s\" en \"%s\" \"%s\" \"%s\"\n", uri, d->manufacturer->value,
214 d->model_name->value, attr ? attr->value->value : "");
215 }
216
217 return (0);
218 }
219
220
221
222
223 #if 0
224
225
226
227 // Scan the command-line...
228 catalog = NULL;
229 outdir = "ppd";
230 src = 0;
231 verbose = 0;
232 locales = NULL;
233 comp = PPDC_NO_COMPRESSION;
234 le = PPDC_LFONLY;
235
236 for (i = 1; i < argc; i ++)
237 if (argv[i][0] == '-')
238 {
239 for (opt = argv[i] + 1; *opt; opt ++)
240 switch (*opt)
241 {
242 case 'c' : // Message catalog...
243 i ++;
244 if (i >= argc)
245 usage();
246
247 if (verbose > 1)
248 printf("ppdc: Loading messages from \"%s\"...\n", argv[i]);
249
250 if (!catalog)
251 catalog = new ppdcCatalog("en");
252
253 if (catalog->load_messages(argv[i]))
254 {
255 fprintf(stderr,
256 "ppdc: Unable to load localization file \"%s\" - %s\n",
257 argv[i], strerror(errno));
258 return (1);
259 }
260 break;
261
262 case 'd' : // Output directory...
263 i ++;
264 if (i >= argc)
265 usage();
266
267 if (verbose > 1)
268 printf("ppdc: Writing PPD files to directory \"%s\"...\n",
269 argv[i]);
270
271 outdir = argv[i];
272 break;
273
274 case 'l' : // Language(s)...
275 i ++;
276 if (i >= argc)
277 usage();
278
279 if (strchr(argv[i], ','))
280 {
281 // Comma-delimited list of languages...
282 char temp[1024], // Copy of language list
283 *start, // Start of current locale name
284 *end; // End of current locale name
285
286
287 locales = new ppdcArray();
288
289 strlcpy(temp, argv[i], sizeof(temp));
290 for (start = temp; *start; start = end)
291 {
292 if ((end = strchr(start, ',')) != NULL)
293 *end++ = '\0';
294 else
295 end = start + strlen(start);
296
297 if (end > start)
298 locales->add(new ppdcString(start));
299 }
300 }
301 else
302 {
303 if (verbose > 1)
304 printf("ppdc: Loading messages for locale \"%s\"...\n",
305 argv[i]);
306
307 if (catalog)
308 delete catalog;
309
310 catalog = new ppdcCatalog(argv[i]);
311
312 if (catalog->messages->count == 0)
313 {
314 fprintf(stderr,
315 "ppdc: Unable to find localization for \"%s\" - %s\n",
316 argv[i], strerror(errno));
317 return (1);
318 }
319 }
320 break;
321
322 case 'I' : // Include directory...
323 i ++;
324 if (i >= argc)
325 usage();
326
327 if (verbose > 1)
328 printf("ppdc: Adding include directory \"%s\"...\n", argv[i]);
329
330 ppdcSource::add_include(argv[i]);
331 break;
332
333 case 'v' : // Be verbose...
334 verbose ++;
335 break;
336
337 case 'z' : // Compress files...
338 comp = PPDC_GZIP_COMPRESSION;
339 break;
340
341 case '-' : // --option
342 if (!strcmp(opt, "-lf"))
343 {
344 le = PPDC_LFONLY;
345 opt += strlen(opt) - 1;
346 break;
347 }
348 else if (!strcmp(opt, "-cr"))
349 {
350 le = PPDC_CRONLY;
351 opt += strlen(opt) - 1;
352 break;
353 }
354 else if (!strcmp(opt, "-crlf"))
355 {
356 le = PPDC_CRLF;
357 opt += strlen(opt) - 1;
358 break;
359 }
360
361 default : // Unknown
362 usage();
363 break;
364 }
365 }
366 else
367 {
368 // Open and load the driver info file...
369 if (verbose > 1)
370 printf("ppdc: Loading driver information file \"%s\"...\n", argv[i]);
371
372 src = new ppdcSource(argv[i]);
373
374 // Create the output directory...
375 if (mkdir(outdir, 0777))
376 {
377 if (errno != EEXIST)
378 {
379 fprintf(stderr, "ppdc: Unable to create output directory %s: %s\n",
380 outdir, strerror(errno));
381 return (1);
382 }
383 }
384
385 // Write PPD files...
386 for (d = (ppdcDriver *)src->drivers->first();
387 d;
388 d = (ppdcDriver *)src->drivers->next())
389 {
390 // Write the PPD file for this driver...
391 for (j = 0; d->pc_file_name->value[j]; j ++)
392 pcfilename[j] = tolower(d->pc_file_name->value[j]);
393
394 pcfilename[j] = '\0';
395
396 if (comp == PPDC_GZIP_COMPRESSION)
397 snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename);
398 else
399 snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename);
400
401 if (verbose)
402 printf("ppdc: Writing %s...\n", filename);
403
404 if (d->write_ppd_file(filename, catalog, locales, src, le, comp))
405 return (1);
406 }
407
408 // Delete the printer driver information...
409 delete src;
410 }
411
412 if (catalog)
413 delete catalog;
414
415 // If no drivers have been loaded, display the program usage message.
416 if (!src)
417 usage();
418
419 // Return with no errors.
420 return (0);
421 }
422 #endif // 0
423
424
425 //
426 // End of "$Id$".
427 //