]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cups-driverd.c
2 * "$Id: cups-driverd.c 6211 2007-01-23 15:44:34Z mike $"
4 * PPD/driver support for the Common UNIX Printing System (CUPS).
6 * This program handles listing and installing both static PPD files
7 * in CUPS_DATADIR/model and dynamically generated PPD files using
8 * the driver helper programs in CUPS_SERVERBIN/driver.
10 * Copyright 1997-2006 by Easy Software Products.
12 * These coded instructions, statements, and computer programs are the
13 * property of Easy Software Products and are protected by Federal
14 * copyright law. Distribution and use rights are outlined in the file
15 * "LICENSE.txt" which should have been included with this file. If this
16 * file is missing or damaged please contact Easy Software Products
19 * Attn: CUPS Licensing Information
20 * Easy Software Products
21 * 44141 Airport View Drive, Suite 204
22 * Hollywood, Maryland 20636 USA
24 * Voice: (301) 373-9600
25 * EMail: cups-info@cups.org
26 * WWW: http://www.cups.org
30 * main() - Scan for drivers and return an IPP response.
31 * add_ppd() - Add a PPD file.
32 * cat_ppd() - Copy a PPD file to stdout.
33 * compare_names() - Compare PPD filenames for sorting.
34 * compare_ppds() - Compare PPD file make and model names for sorting.
35 * list_ppds() - List PPD files.
36 * load_ppds() - Load PPD files recursively.
37 * load_drivers() - Load driver-generated PPD files.
41 * Include necessary headers...
46 #include <cups/transcode.h>
50 * Private PPD functions...
53 extern cups_encoding_t
_ppdGetEncoding(const char *name
);
57 * PPD information structures...
60 typedef struct /**** PPD record ****/
62 time_t mtime
; /* Modification time */
63 size_t size
; /* Size in bytes */
64 char name
[512 - sizeof(time_t) - sizeof(size_t)],
66 natural_language
[128], /* Natural language(s) */
67 make
[128], /* Manufacturer */
68 make_and_model
[128], /* Make and model */
69 device_id
[128]; /* IEEE 1284 Device ID */
72 typedef struct /**** In-memory record ****/
74 int found
; /* 1 if PPD is found */
75 ppd_rec_t record
; /* PPDs.dat record */
83 int NumPPDs
, /* Number of PPD files */
84 SortedPPDs
, /* Number of sorted PPD files */
85 AllocPPDs
; /* Number of allocated entries */
86 ppd_info_t
*PPDs
; /* PPD file info */
87 int ChangedPPD
; /* Did we change the PPD database? */
94 static ppd_info_t
*add_ppd(const char *name
, const char *natural_language
,
95 const char *make
, const char *make_and_model
,
96 const char *device_id
, time_t mtime
, size_t size
);
97 static int cat_ppd(const char *name
);
98 static int compare_names(const ppd_info_t
*p0
,
99 const ppd_info_t
*p1
);
100 static int compare_ppds(const ppd_info_t
*p0
,
101 const ppd_info_t
*p1
);
102 static int list_ppds(int request_id
, int limit
, const char *opt
);
103 static int load_drivers(void);
104 static int load_ppds(const char *d
, const char *p
);
108 * 'main()' - Scan for drivers and return an IPP response.
112 * cups-driverd request_id limit options
115 int /* O - Exit code */
116 main(int argc
, /* I - Number of command-line args */
117 char *argv
[]) /* I - Command-line arguments */
120 * Install or list PPDs...
123 if (argc
== 3 && !strcmp(argv
[1], "cat"))
124 return (cat_ppd(argv
[2]));
125 else if (argc
== 5 && !strcmp(argv
[1], "list"))
126 return (list_ppds(atoi(argv
[2]), atoi(argv
[3]), argv
[4]));
129 fputs("Usage: cups-driverd cat ppd-name\n", stderr
);
130 fputs("Usage: cups-driverd list request_id limit options\n", stderr
);
137 * 'add_ppd()' - Add a PPD file.
140 static ppd_info_t
* /* O - PPD */
141 add_ppd(const char *name
, /* I - PPD name */
142 const char *natural_language
, /* I - Language(s) */
143 const char *make
, /* I - Manufacturer */
144 const char *make_and_model
, /* I - NickName */
145 const char *device_id
, /* I - 1284DeviceID */
146 time_t mtime
, /* I - Modification time */
147 size_t size
) /* I - File size */
149 ppd_info_t
*ppd
; /* PPD */
150 char *recommended
; /* Foomatic driver string */
154 * Add a new PPD file...
157 if (NumPPDs
>= AllocPPDs
)
160 * Allocate (more) memory for the PPD files...
166 ppd
= malloc(sizeof(ppd_info_t
) * AllocPPDs
);
168 ppd
= realloc(PPDs
, sizeof(ppd_info_t
) * AllocPPDs
);
172 fprintf(stderr
, "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n",
180 ppd
= PPDs
+ NumPPDs
;
184 * Zero-out the PPD data and copy the values over...
187 memset(ppd
, 0, sizeof(ppd_info_t
));
190 ppd
->record
.mtime
= mtime
;
191 ppd
->record
.size
= size
;
193 strlcpy(ppd
->record
.name
, name
, sizeof(ppd
->record
.name
));
194 strlcpy(ppd
->record
.natural_language
, natural_language
,
195 sizeof(ppd
->record
.natural_language
));
196 strlcpy(ppd
->record
.make
, make
, sizeof(ppd
->record
.make
));
197 strlcpy(ppd
->record
.make_and_model
, make_and_model
,
198 sizeof(ppd
->record
.make_and_model
));
199 strlcpy(ppd
->record
.device_id
, device_id
, sizeof(ppd
->record
.device_id
));
202 * Strip confusing (and often wrong) "recommended" suffix added by
203 * Foomatic drivers...
206 if ((recommended
= strstr(ppd
->record
.make_and_model
, " (recommended)")) != NULL
)
210 * Return the new PPD pointer...
218 * 'cat_ppd()' - Copy a PPD file to stdout.
221 static int /* O - Exit code */
222 cat_ppd(const char *name
) /* I - PPD name */
224 char scheme
[256], /* Scheme from PPD name */
225 *sptr
; /* Pointer into scheme */
226 char line
[1024]; /* Line/filename */
230 * Figure out if this is a static or dynamic PPD file...
233 strlcpy(scheme
, name
, sizeof(scheme
));
234 if ((sptr
= strchr(scheme
, ':')) != NULL
)
238 if (!strcmp(scheme
, "file"))
241 * "file:name" == "name"...
254 * Dynamic PPD, see if we have a driver program to support it...
257 const char *serverbin
; /* CUPS_SERVERBIN env var */
260 if ((serverbin
= getenv("CUPS_SERVERBIN")) == NULL
)
261 serverbin
= CUPS_SERVERBIN
;
263 snprintf(line
, sizeof(line
), "%s/driver/%s", serverbin
, scheme
);
264 if (access(line
, X_OK
))
267 * File does not exist or is not executable...
270 fprintf(stderr
, "ERROR: [cups-driverd] Unable to access \"%s\" - %s\n",
271 line
, strerror(errno
));
276 * Yes, let it cat the PPD file...
279 if (execl(line
, scheme
, "cat", name
, (char *)NULL
))
282 * Unable to execute driver...
285 fprintf(stderr
, "ERROR: [cups-driverd] Unable to execute \"%s\" - %s\n",
286 line
, strerror(errno
));
293 * Static PPD, see if we have a valid path and it exists...
296 cups_file_t
*fp
; /* PPD file */
297 const char *datadir
; /* CUPS_DATADIR env var */
300 if (name
[0] == '/' || strstr(name
, "../") || strstr(name
, "/.."))
306 fprintf(stderr
, "ERROR: [cups-driverd] Bad PPD name \"%s\"!\n", name
);
311 * Try opening the file...
314 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
315 datadir
= CUPS_DATADIR
;
317 snprintf(line
, sizeof(line
), "%s/model/%s", datadir
, name
);
318 if ((fp
= cupsFileOpen(line
, "r")) == NULL
)
320 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n",
321 line
, strerror(errno
));
326 * Now copy the file to stdout...
329 while (cupsFileGets(fp
, line
, sizeof(line
)))
336 * Return with no errors...
344 * 'compare_names()' - Compare PPD filenames for sorting.
347 static int /* O - Result of comparison */
348 compare_names(const ppd_info_t
*p0
, /* I - First PPD file */
349 const ppd_info_t
*p1
) /* I - Second PPD file */
351 return (strcasecmp(p0
->record
.name
, p1
->record
.name
));
356 * 'compare_ppds()' - Compare PPD file make and model names for sorting.
359 static int /* O - Result of comparison */
360 compare_ppds(const ppd_info_t
*p0
, /* I - First PPD file */
361 const ppd_info_t
*p1
) /* I - Second PPD file */
363 int diff
; /* Difference between strings */
367 * First compare manufacturers...
370 if ((diff
= strcasecmp(p0
->record
.make
, p1
->record
.make
)) != 0)
372 else if ((diff
= cupsdCompareNames(p0
->record
.make_and_model
,
373 p1
->record
.make_and_model
)) != 0)
376 return (strcasecmp(p0
->record
.natural_language
,
377 p1
->record
.natural_language
));
382 * 'list_ppds()' - List PPD files.
385 static int /* O - Exit code */
386 list_ppds(int request_id
, /* I - Request ID */
387 int limit
, /* I - Limit */
388 const char *opt
) /* I - Option argument */
390 int i
; /* Looping var */
391 int count
; /* Number of PPDs to send */
392 ppd_info_t
*ppd
; /* Current PPD file */
393 cups_file_t
*fp
; /* ppds.dat file */
394 struct stat fileinfo
; /* ppds.dat information */
395 char filename
[1024], /* ppds.dat filename */
396 model
[1024]; /* Model directory */
397 const char *cups_cachedir
; /* CUPS_CACHEDIR environment variable */
398 const char *cups_datadir
; /* CUPS_DATADIR environment variable */
399 int num_options
; /* Number of options */
400 cups_option_t
*options
; /* Options */
401 const char *requested
, /* requested-attributes option */
402 *make
; /* ppd-make option */
403 int send_natural_language
, /* Send ppd-natural-language attribute? */
404 send_make
, /* Send ppd-make attribute? */
405 send_make_and_model
, /* Send ppd-make-and-model attribute? */
406 send_name
, /* Send ppd-name attribute? */
407 send_device_id
; /* Send ppd-device-id attribute? */
410 fprintf(stderr
, "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, opt=\"%s\"\n",
411 request_id
, limit
, opt
);
414 * See if we a PPD database file...
419 PPDs
= (ppd_info_t
*)NULL
;
422 if ((cups_cachedir
= getenv("CUPS_CACHEDIR")) == NULL
)
423 cups_cachedir
= CUPS_CACHEDIR
;
425 snprintf(filename
, sizeof(filename
), "%s/ppds.dat", cups_cachedir
);
426 if (!stat(filename
, &fileinfo
) &&
427 (fileinfo
.st_size
% sizeof(ppd_rec_t
)) == 0 &&
428 (NumPPDs
= fileinfo
.st_size
/ sizeof(ppd_rec_t
)) > 0)
431 * We have a ppds.dat file, so read it!
436 if ((PPDs
= malloc(sizeof(ppd_info_t
) * NumPPDs
)) == NULL
)
439 "ERROR: [cups-driverd] Unable to allocate memory for %d "
440 "PPD files!\n", NumPPDs
);
444 else if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
446 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
448 cupsFileRead(fp
, (char *)&(ppd
->record
), sizeof(ppd_rec_t
));
454 fprintf(stderr
, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n",
459 fprintf(stderr
, "ERROR: [cups-driverd] Unable to read \"%s\" - %s\n", filename
,
466 * Load all PPDs in the specified directory and below...
469 SortedPPDs
= NumPPDs
;
471 if ((cups_datadir
= getenv("CUPS_DATADIR")) == NULL
)
472 cups_datadir
= CUPS_DATADIR
;
474 snprintf(model
, sizeof(model
), "%s/model", cups_datadir
);
475 load_ppds(model
, "");
478 * Cull PPD files that are no longer present...
481 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
485 * Remove this PPD file from the list...
489 memmove(ppd
, ppd
+ 1, (i
- 1) * sizeof(ppd_info_t
));
496 * Sort the PPDs by name...
500 qsort(PPDs
, NumPPDs
, sizeof(ppd_info_t
),
501 (int (*)(const void *, const void *))compare_names
);
504 * Write the new ppds.dat file...
509 if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
511 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
512 cupsFileWrite(fp
, (char *)&(ppd
->record
), sizeof(ppd_rec_t
));
516 fprintf(stderr
, "INFO: [cups-driverd] Wrote \"%s\", %d PPDs...\n",
520 fprintf(stderr
, "ERROR: [cups-driverd] Unable to write \"%s\" - %s\n",
521 filename
, strerror(errno
));
524 fputs("INFO: [cups-driverd] No new or changed PPDs...\n", stderr
);
527 * Scan for dynamic PPD files...
533 * Add the raw driver...
536 add_ppd("raw", "en", "Raw", "Raw Queue", "", 0, 0);
539 * Sort the PPDs by make and model...
543 qsort(PPDs
, NumPPDs
, sizeof(ppd_info_t
),
544 (int (*)(const void *, const void *))compare_ppds
);
547 * Send IPP attributes...
550 num_options
= cupsParseOptions(opt
, 0, &options
);
551 requested
= cupsGetOption("requested-attributes", num_options
, options
);
552 make
= cupsGetOption("ppd-make", num_options
, options
);
554 fprintf(stderr
, "DEBUG: [cups-driverd] requested=\"%s\"\n",
555 requested
? requested
: "(nil)");
557 if (!requested
|| strstr(requested
, "all"))
561 send_make_and_model
= 1;
562 send_natural_language
= 1;
567 send_name
= strstr(requested
, "ppd-name") != NULL
;
568 send_make
= strstr(requested
, "ppd-make,") != NULL
||
569 strstr(requested
, ",ppd-make") != NULL
||
570 !strcmp(requested
, "ppd-make");
571 send_make_and_model
= strstr(requested
, "ppd-make-and-model") != NULL
;
572 send_natural_language
= strstr(requested
, "ppd-natural-language") != NULL
;
573 send_device_id
= strstr(requested
, "ppd-device-id") != NULL
;
576 puts("Content-Type: application/ipp\n");
578 cupsdSendIPPHeader(IPP_OK
, request_id
);
579 cupsdSendIPPGroup(IPP_TAG_OPERATION
);
580 cupsdSendIPPString(IPP_TAG_CHARSET
, "attributes-charset", "utf-8");
581 cupsdSendIPPString(IPP_TAG_LANGUAGE
, "attributes-natural-language", "en-US");
583 if (limit
<= 0 || limit
> NumPPDs
)
588 for (i
= NumPPDs
, ppd
= PPDs
; count
> 0 && i
> 0; i
--, ppd
++)
589 if (!make
|| !strcasecmp(ppd
->record
.make
, make
))
595 fprintf(stderr
, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
596 ppd
->record
.name
, ppd
->record
.make_and_model
);
600 cupsdSendIPPGroup(IPP_TAG_PRINTER
);
603 cupsdSendIPPString(IPP_TAG_NAME
, "ppd-name", ppd
->record
.name
);
605 if (send_natural_language
)
606 cupsdSendIPPString(IPP_TAG_LANGUAGE
, "ppd-natural-language",
607 ppd
->record
.natural_language
);
610 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-make", ppd
->record
.make
);
612 if (send_make_and_model
)
613 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-make-and-model",
614 ppd
->record
.make_and_model
);
617 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-device-id",
618 ppd
->record
.device_id
);
621 * If we have only requested the ppd-make attribute, then skip
622 * the remaining PPDs with this make...
625 if (requested
&& !strcmp(requested
, "ppd-make"))
627 const char *this_make
; /* This ppd-make */
630 for (this_make
= ppd
->record
.make
, i
--, ppd
++; i
> 0; i
--, ppd
++)
631 if (strcasecmp(this_make
, ppd
->record
.make
))
639 cupsdSendIPPTrailer();
646 * 'load_ppds()' - Load PPD files recursively.
649 static int /* O - 1 on success, 0 on failure */
650 load_ppds(const char *d
, /* I - Actual directory */
651 const char *p
) /* I - Virtual path in name */
653 int i
; /* Looping var */
654 cups_file_t
*fp
; /* Pointer to file */
655 cups_dir_t
*dir
; /* Directory pointer */
656 cups_dentry_t
*dent
; /* Directory entry */
657 char filename
[1024], /* Name of PPD or directory */
658 line
[256], /* Line from backend */
659 *ptr
, /* Pointer into name */
660 name
[128], /* Name of PPD file */
661 lang_version
[64], /* PPD LanguageVersion */
662 lang_encoding
[64], /* PPD LanguageEncoding */
663 country
[64], /* Country code */
664 manufacturer
[256], /* Manufacturer */
665 make_model
[256], /* Make and Model */
666 model_name
[256], /* ModelName */
667 nick_name
[256], /* NickName */
668 device_id
[256]; /* 1284DeviceID */
669 ppd_info_t
*ppd
, /* New PPD file */
670 key
; /* Search key */
671 int new_ppd
; /* Is this a new PPD? */
672 struct /* LanguageVersion translation table */
674 const char *version
, /* LanguageVersion string */
675 *language
; /* Language code */
687 { "japanese", "jp" },
688 { "norwegian", "no" },
690 { "portuguese", "pt" },
699 if ((dir
= cupsDirOpen(d
)) == NULL
)
701 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n",
706 while ((dent
= cupsDirRead(dir
)) != NULL
)
709 * Skip files/directories starting with "."...
712 if (dent
->filename
[0] == '.')
716 * See if this is a file...
719 snprintf(filename
, sizeof(filename
), "%s/%s", d
, dent
->filename
);
722 snprintf(name
, sizeof(name
), "%s/%s", p
, dent
->filename
);
724 strlcpy(name
, dent
->filename
, sizeof(name
));
726 if (S_ISDIR(dent
->fileinfo
.st_mode
))
732 if (!load_ppds(filename
, name
))
742 * See if this file has been scanned before...
747 strcpy(key
.record
.name
, name
);
749 ppd
= bsearch(&key
, PPDs
, SortedPPDs
, sizeof(ppd_info_t
),
750 (int (*)(const void *, const void *))compare_names
);
753 ppd
->record
.size
== dent
->fileinfo
.st_size
&&
754 ppd
->record
.mtime
== dent
->fileinfo
.st_mtime
)
764 * No, file is new/changed, so re-scan it...
767 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
771 * Now see if this is a PPD file...
775 cupsFileGets(fp
, line
, sizeof(line
));
777 if (strncmp(line
, "*PPD-Adobe:", 11))
780 * Nope, close the file and continue...
789 * Now read until we get the NickName field...
792 model_name
[0] = '\0';
794 manufacturer
[0] = '\0';
796 lang_encoding
[0] = '\0';
797 strcpy(lang_version
, "en");
799 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
801 if (!strncmp(line
, "*Manufacturer:", 14))
802 sscanf(line
, "%*[^\"]\"%255[^\"]", manufacturer
);
803 else if (!strncmp(line
, "*ModelName:", 11))
804 sscanf(line
, "%*[^\"]\"%127[^\"]", model_name
);
805 else if (!strncmp(line
, "*LanguageEncoding:", 18))
806 sscanf(line
, "%*[^:]:%63s", lang_encoding
);
807 else if (!strncmp(line
, "*LanguageVersion:", 17))
808 sscanf(line
, "%*[^:]:%63s", lang_version
);
809 else if (!strncmp(line
, "*NickName:", 10))
810 sscanf(line
, "%*[^\"]\"%255[^\"]", nick_name
);
811 else if (!strncasecmp(line
, "*1284DeviceID:", 14))
812 sscanf(line
, "%*[^\"]\"%255[^\"]", device_id
);
813 else if (!strncmp(line
, "*OpenUI", 7))
816 * Stop early if we have a NickName or ModelName attributes
817 * before the first OpenUI...
820 if (model_name
[0] || nick_name
[0])
832 * See if we got all of the required info...
836 cupsCharsetToUTF8((cups_utf8_t
*)make_model
, nick_name
,
837 sizeof(make_model
), _ppdGetEncoding(lang_encoding
));
839 strcpy(make_model
, model_name
);
841 while (isspace(make_model
[0] & 255))
842 _cups_strcpy(make_model
, make_model
+ 1);
845 continue; /* Nope... */
848 * See if we got a manufacturer...
851 while (isspace(manufacturer
[0] & 255))
852 _cups_strcpy(manufacturer
, manufacturer
+ 1);
854 if (!manufacturer
[0] || !strcmp(manufacturer
, "ESP"))
857 * Nope, copy the first part of the make and model then...
860 strlcpy(manufacturer
, make_model
, sizeof(manufacturer
));
863 * Truncate at the first space, dash, or slash, or make the
864 * manufacturer "Other"...
867 for (ptr
= manufacturer
; *ptr
; ptr
++)
868 if (*ptr
== ' ' || *ptr
== '-' || *ptr
== '/')
871 if (*ptr
&& ptr
> manufacturer
)
873 else if (!strncasecmp(manufacturer
, "agfa", 4))
874 strcpy(manufacturer
, "AGFA");
875 else if (!strncasecmp(manufacturer
, "herk", 4) ||
876 !strncasecmp(manufacturer
, "linotype", 8))
877 strcpy(manufacturer
, "LHAG");
879 strcpy(manufacturer
, "Other");
882 * Hack for various vendors...
885 if (!strcasecmp(manufacturer
, "XPrint"))
886 strcpy(manufacturer
, "Xerox");
887 else if (!strcasecmp(manufacturer
, "Eastman"))
888 strcpy(manufacturer
, "Kodak");
889 else if (!strcasecmp(manufacturer
, "laserwriter"))
890 strcpy(manufacturer
, "Apple");
891 else if (!strcasecmp(manufacturer
, "colorpoint"))
892 strcpy(manufacturer
, "Seiko");
893 else if (!strcasecmp(manufacturer
, "fiery"))
894 strcpy(manufacturer
, "EFI");
895 else if (!strcasecmp(manufacturer
, "ps") ||
896 !strcasecmp(manufacturer
, "colorpass"))
897 strcpy(manufacturer
, "Canon");
898 else if (!strncasecmp(manufacturer
, "primera", 7))
899 strcpy(manufacturer
, "Fargo");
900 else if (!strcasecmp(manufacturer
, "designjet"))
901 strcpy(manufacturer
, "HP");
903 else if (!strncasecmp(manufacturer
, "LHAG", 4) ||
904 !strncasecmp(manufacturer
, "linotype", 8))
905 strcpy(manufacturer
, "LHAG");
908 * Fix the lang_version as needed...
911 if ((ptr
= strchr(lang_version
, '-')) != NULL
)
913 else if ((ptr
= strchr(lang_version
, '_')) != NULL
)
919 * Setup the country suffix...
923 _cups_strcpy(country
+ 1, ptr
);
928 * No country suffix...
934 for (i
= 0; i
< (int)(sizeof(languages
) / sizeof(languages
[0])); i
++)
935 if (!strcasecmp(languages
[i
].version
, lang_version
))
938 if (i
< (int)(sizeof(languages
) / sizeof(languages
[0])))
941 * Found a known language...
944 snprintf(lang_version
, sizeof(lang_version
), "%s%s",
945 languages
[i
].language
, country
);
950 * Unknown language; use "xx"...
953 strcpy(lang_version
, "xx");
957 * Add the PPD file...
965 * Add new PPD file...
968 fprintf(stderr
, "DEBUG: [cups-driverd] Adding ppd \"%s\"...\n", name
);
970 if (!add_ppd(name
, lang_version
, manufacturer
, make_model
, device_id
,
971 dent
->fileinfo
.st_mtime
, dent
->fileinfo
.st_size
))
980 * Update existing record...
983 fprintf(stderr
, "DEBUG: [cups-driverd] Updating ppd \"%s\"...\n", name
);
985 memset(ppd
, 0, sizeof(ppd_info_t
));
988 ppd
->record
.mtime
= dent
->fileinfo
.st_mtime
;
989 ppd
->record
.size
= dent
->fileinfo
.st_size
;
991 strlcpy(ppd
->record
.name
, name
, sizeof(ppd
->record
.name
));
992 strlcpy(ppd
->record
.make
, manufacturer
, sizeof(ppd
->record
.make
));
993 strlcpy(ppd
->record
.make_and_model
, make_model
,
994 sizeof(ppd
->record
.make_and_model
));
995 strlcpy(ppd
->record
.natural_language
, lang_version
,
996 sizeof(ppd
->record
.natural_language
));
997 strlcpy(ppd
->record
.device_id
, device_id
, sizeof(ppd
->record
.device_id
));
1010 * 'load_drivers()' - Load driver-generated PPD files.
1013 static int /* O - 1 on success, 0 on failure */
1016 const char *server_bin
; /* CUPS_SERVERBIN environment variable */
1017 char drivers
[1024]; /* Location of driver programs */
1018 FILE *fp
; /* Pipe to driver program */
1019 cups_dir_t
*dir
; /* Directory pointer */
1020 cups_dentry_t
*dent
; /* Directory entry */
1021 char filename
[1024], /* Name of driver */
1022 line
[2048], /* Line from driver */
1023 name
[512], /* ppd-name */
1024 natural_language
[128], /* ppd-natural-language */
1025 make
[128], /* ppd-make */
1026 make_and_model
[256], /* ppd-make-and-model */
1027 device_id
[256]; /* ppd-device-id */
1031 * Try opening the driver directory...
1034 if ((server_bin
= getenv("CUPS_SERVERBIN")) == NULL
)
1035 server_bin
= CUPS_SERVERBIN
;
1037 snprintf(drivers
, sizeof(drivers
), "%s/driver", server_bin
);
1039 if ((dir
= cupsDirOpen(drivers
)) == NULL
)
1041 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open driver directory "
1043 drivers
, strerror(errno
));
1048 * Loop through all of the device drivers...
1051 while ((dent
= cupsDirRead(dir
)) != NULL
)
1054 * Only look at executable files...
1057 if (!(dent
->fileinfo
.st_mode
& 0111) || !S_ISREG(dent
->fileinfo
.st_mode
))
1061 * Run the driver with no arguments and collect the output...
1064 snprintf(filename
, sizeof(filename
), "%s/%s list", drivers
, dent
->filename
);
1065 if ((fp
= popen(filename
, "r")) != NULL
)
1067 while (fgets(line
, sizeof(line
), fp
) != NULL
)
1070 * Each line is of the form:
1072 * \"ppd-name\" ppd-natural-language "ppd-make" "ppd-make-and-model"
1075 device_id
[0] = '\0';
1077 if (sscanf(line
, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\""
1078 "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\"",
1079 name
, natural_language
, make
, make_and_model
,
1083 * Bad format; strip trailing newline and write an error message.
1086 if (line
[strlen(line
) - 1] == '\n')
1087 line
[strlen(line
) - 1] = '\0';
1089 fprintf(stderr
, "ERROR: [cups-driverd] Bad line from \"%s\": %s\n",
1090 dent
->filename
, line
);
1096 * Add the device to the array of available devices...
1099 if (!add_ppd(name
, natural_language
, make
, make_and_model
, device_id
,
1106 fprintf(stderr
, "DEBUG: [cups-driverd] Added dynamic PPD \"%s\"...\n",
1114 fprintf(stderr
, "WARNING: [cups-driverd] Unable to execute \"%s\": %s\n",
1115 filename
, strerror(errno
));
1125 * End of "$Id: cups-driverd.c 6211 2007-01-23 15:44:34Z mike $".