]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/ppds.c
2 * "$Id: ppds.c,v 1.4 2000/02/11 05:04:14 mike Exp $"
4 * PPD scanning routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2000 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * LoadPPDs() - Load PPD files from the specified directory...
27 * load_ppds() - Load PPD files recursively.
31 * Include necessary headers...
39 #endif /* HAVE_LIBZ */
43 typedef struct dirent DIRENT
;
44 # define NAMLEN(dirent) strlen((dirent)->d_name)
47 # include <sys/ndir.h>
55 typedef struct direct DIRENT
;
56 # define NAMLEN(dirent) (dirent)->d_namlen
61 * PPD information structure...
66 char ppd_make
[128], /* Manufacturer */
67 ppd_make_and_model
[256], /* Make and model */
68 ppd_name
[256], /* PPD filename */
69 ppd_natural_language
[16]; /* Natural language */
77 static int num_ppds
, /* Number of PPD files */
78 alloc_ppds
; /* Number of allocated entries */
79 static ppd_info_t
*ppds
; /* PPD file info */
86 static int compare_ppds(const ppd_info_t
*p0
, const ppd_info_t
*p1
);
87 static void load_ppds(const char *d
, const char *p
);
91 * 'LoadPPDs()' - Load PPD files from the specified directory...
95 LoadPPDs(const char *d
) /* I - Directory to scan... */
97 int i
; /* Looping var */
98 ppd_info_t
*ppd
; /* Current PPD file */
102 * Load all PPDs in the specified directory and below...
107 ppds
= (ppd_info_t
*)0;
116 qsort(ppds
, num_ppds
, sizeof(ppd_info_t
),
117 (int (*)(const void *, const void *))compare_ppds
);
120 * Create the list of PPDs...
125 for (i
= num_ppds
, ppd
= ppds
; i
> 0; i
--, ppd
++)
128 ippAddSeparator(PPDs
);
130 ippAddString(PPDs
, IPP_TAG_PRINTER
, IPP_TAG_NAME
,
131 "ppd-name", NULL
, ppd
->ppd_name
);
132 ippAddString(PPDs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
133 "ppd-make", NULL
, ppd
->ppd_make
);
134 ippAddString(PPDs
, IPP_TAG_PRINTER
, IPP_TAG_TEXT
,
135 "ppd-make-and-model", NULL
, ppd
->ppd_make_and_model
);
136 ippAddString(PPDs
, IPP_TAG_PRINTER
, IPP_TAG_LANGUAGE
,
137 "ppd-natural-language", NULL
, ppd
->ppd_natural_language
);
141 * Free the memory used...
150 * 'compare_ppds()' - Compare PPD file make and model names for sorting.
153 static int /* O - Result of comparison */
154 compare_ppds(const ppd_info_t
*p0
, /* I - First PPD file */
155 const ppd_info_t
*p1
) /* I - Second PPD file */
157 const char *s
, /* First name */
158 *t
; /* Second name */
159 int diff
, /* Difference between digits */
160 digits
; /* Number of digits */
164 * First compare manufacturers...
167 if ((diff
= strcasecmp(p0
->ppd_make
, p1
->ppd_make
)) != 0)
171 * Then compare names...
174 s
= p0
->ppd_make_and_model
;
175 t
= p1
->ppd_make_and_model
;
178 * Loop through both nicknames, returning only when a difference is
179 * seen. Also, compare whole numbers rather than just characters, too!
184 if (isdigit(*s
) && isdigit(*t
))
187 * Got a number; start by skipping leading 0's...
196 * Skip equal digits...
199 while (isdigit(*s
) && *s
== *t
)
206 * Bounce out if *s and *t aren't both digits...
209 if (isdigit(*s
) && !isdigit(*t
))
211 else if (!isdigit(*s
) && isdigit(*t
))
213 else if (!isdigit(*s
) || !isdigit(*t
))
222 * Figure out how many more digits there are...
242 * Return if the number or value of the digits is different...
252 else if (tolower(*s
) < tolower(*t
))
254 else if (tolower(*s
) > tolower(*t
))
264 * Return the results of the final comparison...
272 return (strcasecmp(p0
->ppd_natural_language
, p1
->ppd_natural_language
));
277 * 'load_ppds()' - Load PPD files recursively.
281 load_ppds(const char *d
, /* I - Actual directory */
282 const char *p
) /* I - Virtual path in name */
285 gzFile fp
; /* Pointer to file */
287 FILE *fp
; /* Pointer to file */
288 #endif /* HAVE_LIBZ */
289 DIR *dir
; /* Directory pointer */
290 DIRENT
*dent
; /* Directory entry */
291 struct stat fileinfo
; /* File information */
292 char filename
[1024], /* Name of backend */
293 line
[1024], /* Line from backend */
294 *ptr
, /* Pointer into name */
295 name
[128], /* Name of PPD file */
296 language
[64], /* Device class */
297 manufacturer
[1024], /* Manufacturer */
298 make_model
[256]; /* Make and model */
299 ppd_info_t
*ppd
; /* New PPD file */
302 if ((dir
= opendir(d
)) == NULL
)
304 LogMessage(L_ERROR
, "LoadPPDs: Unable to open PPD directory \"%s\": %s",
309 while ((dent
= readdir(dir
)) != NULL
)
312 * Skip "." and ".."...
315 if (dent
->d_name
[0] == '.')
319 * See if this is a file...
322 snprintf(filename
, sizeof(filename
), "%s/%s", d
, dent
->d_name
);
325 snprintf(name
, sizeof(name
), "%s/%s", p
, dent
->d_name
);
327 strcpy(name
, dent
->d_name
);
329 if (stat(filename
, &fileinfo
))
332 if (S_ISDIR(fileinfo
.st_mode
))
338 load_ppds(filename
, name
);
343 if ((fp
= gzopen(filename
, "rb")) == NULL
)
345 if ((fp
= fopen(filename
, "rb")) == NULL
)
346 #endif /* HAVE_LIBZ */
350 * Yup, now see if this is a PPD file...
355 gzgets(fp
, line
, sizeof(line
));
357 fgets(line
, sizeof(line
), fp
);
358 #endif /* HAVE_LIBZ */
360 if (strncmp(line
, "*PPD-Adobe:", 11) != 0)
363 * Nope, close the file and continue...
370 #endif /* HAVE_LIBZ */
376 * Now read until we get the NickName field...
379 make_model
[0] = '\0';
380 manufacturer
[0] = '\0';
381 strcpy(language
, "en");
384 while (gzgets(fp
, line
, sizeof(line
)) != NULL
)
386 while (fgets(line
, sizeof(line
), fp
) != NULL
)
387 #endif /* HAVE_LIBZ */
389 if (strncmp(line
, "*Manufacturer:", 14) == 0)
390 sscanf(line
, "%*[^\"]\"%255[^\"]", manufacturer
);
391 else if (strncmp(line
, "*ModelName:", 11) == 0)
392 sscanf(line
, "%*[^\"]\"%127[^\"]", make_model
);
393 else if (strncmp(line
, "*LanguageVersion:", 17) == 0)
394 sscanf(line
, "%*[^\"]\"%63[^\"]", language
);
395 else if (strncmp(line
, "*NickName:", 10) == 0)
397 sscanf(line
, "%*[^\"]\"%255[^\"]", make_model
);
410 #endif /* HAVE_LIBZ */
413 * See if we got all of the required info...
416 while (isspace(make_model
[0]))
417 strcpy(make_model
, make_model
+ 1);
420 continue; /* Nope... */
423 * See if we got a manufacturer...
426 while (isspace(manufacturer
[0]))
427 strcpy(manufacturer
, manufacturer
+ 1);
429 if (manufacturer
[0] || strcmp(manufacturer
, "ESP") == 0)
432 * Nope, copy the first part of the make and model then...
435 strncpy(manufacturer
, make_model
, sizeof(manufacturer
) - 1);
438 * Truncate at the first space, dash, or slash, or make the
439 * manufacturer "Other"...
442 for (ptr
= manufacturer
; *ptr
; ptr
++)
443 if (*ptr
== ' ' || *ptr
== '-' || *ptr
== '/')
446 if (*ptr
&& ptr
> manufacturer
)
448 else if (strncasecmp(manufacturer
, "agfa", 4) == 0)
449 strcpy(manufacturer
, "AGFA");
450 else if (strncasecmp(manufacturer
, "ps-ipu", 6) == 0)
451 strcpy(manufacturer
, "Canon");
452 else if (strncasecmp(manufacturer
, "herk", 4) == 0)
453 strcpy(manufacturer
, "Linotype");
455 strcpy(manufacturer
, "Other");
458 * Hack for various vendors...
461 if (strcasecmp(manufacturer
, "XPrint") == 0)
462 strcpy(manufacturer
, "Xerox");
463 else if (strcasecmp(manufacturer
, "Eastman") == 0)
464 strcpy(manufacturer
, "Kodak");
465 else if (strcasecmp(manufacturer
, "laserwriter") == 0)
466 strcpy(manufacturer
, "Apple");
467 else if (strcasecmp(manufacturer
, "colorpoint") == 0)
468 strcpy(manufacturer
, "Seiko");
469 else if (strcasecmp(manufacturer
, "fiery") == 0)
470 strcpy(manufacturer
, "EFI");
471 else if (strncasecmp(manufacturer
, "primera", 7) == 0)
472 strcpy(manufacturer
, "Fargo");
476 * Fix the language as needed...
479 if (strcasecmp(language
, "german") == 0)
480 strcpy(language
, "de");
481 else if (strcasecmp(language
, "spanish") == 0)
482 strcpy(language
, "es");
483 else if (strlen(language
) > 2)
489 language
[0] = tolower(language
[0]);
490 language
[1] = tolower(language
[1]);
495 * Add the PPD file...
498 if (num_ppds
>= alloc_ppds
)
501 * Allocate (more) memory for the PPD files...
505 ppd
= malloc(sizeof(ppd_info_t
) * 32);
507 ppd
= realloc(ppds
, sizeof(ppd_info_t
) * (alloc_ppds
+ 32));
511 LogMessage(L_ERROR
, "load_ppds: Ran out of memory for %d PPD files!",
521 ppd
= ppds
+ num_ppds
;
524 memset(ppd
, 0, sizeof(ppd_info_t
));
525 strncpy(ppd
->ppd_name
, name
, sizeof(ppd
->ppd_name
) - 1);
526 strncpy(ppd
->ppd_make
, manufacturer
, sizeof(ppd
->ppd_make
) - 1);
527 strncpy(ppd
->ppd_make_and_model
, make_model
,
528 sizeof(ppd
->ppd_make_and_model
) - 1);
529 strncpy(ppd
->ppd_natural_language
, language
,
530 sizeof(ppd
->ppd_natural_language
) - 1);
532 LogMessage(L_DEBUG
, "LoadPPDs: Added ppd \"%s\"...", name
);
540 * End of "$Id: ppds.c,v 1.4 2000/02/11 05:04:14 mike Exp $".