]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cups-driverd.c
cbe2ebd32140120526255fdc3eb7a1ea41fb7217
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 */
153 * Add a new PPD file...
156 if (NumPPDs
>= AllocPPDs
)
159 * Allocate (more) memory for the PPD files...
165 ppd
= malloc(sizeof(ppd_info_t
) * AllocPPDs
);
167 ppd
= realloc(PPDs
, sizeof(ppd_info_t
) * AllocPPDs
);
171 fprintf(stderr
, "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n",
179 ppd
= PPDs
+ NumPPDs
;
183 * Zero-out the PPD data and copy the values over...
186 memset(ppd
, 0, sizeof(ppd_info_t
));
189 ppd
->record
.mtime
= mtime
;
190 ppd
->record
.size
= size
;
192 strlcpy(ppd
->record
.name
, name
, sizeof(ppd
->record
.name
));
193 strlcpy(ppd
->record
.natural_language
, natural_language
,
194 sizeof(ppd
->record
.natural_language
));
195 strlcpy(ppd
->record
.make
, make
, sizeof(ppd
->record
.make
));
196 strlcpy(ppd
->record
.make_and_model
, make_and_model
,
197 sizeof(ppd
->record
.make_and_model
));
198 strlcpy(ppd
->record
.device_id
, device_id
, sizeof(ppd
->record
.device_id
));
201 * Return the new PPD pointer...
209 * 'cat_ppd()' - Copy a PPD file to stdout.
212 static int /* O - Exit code */
213 cat_ppd(const char *name
) /* I - PPD name */
215 char scheme
[256], /* Scheme from PPD name */
216 *sptr
; /* Pointer into scheme */
217 char line
[1024]; /* Line/filename */
221 * Figure out if this is a static or dynamic PPD file...
224 strlcpy(scheme
, name
, sizeof(scheme
));
225 if ((sptr
= strchr(scheme
, ':')) != NULL
)
229 if (!strcmp(scheme
, "file"))
232 * "file:name" == "name"...
245 * Dynamic PPD, see if we have a driver program to support it...
248 const char *serverbin
; /* CUPS_SERVERBIN env var */
251 if ((serverbin
= getenv("CUPS_SERVERBIN")) == NULL
)
252 serverbin
= CUPS_SERVERBIN
;
254 snprintf(line
, sizeof(line
), "%s/driver/%s", serverbin
, scheme
);
255 if (access(line
, X_OK
))
258 * File does not exist or is not executable...
261 fprintf(stderr
, "ERROR: [cups-driverd] Unable to access \"%s\" - %s\n",
262 line
, strerror(errno
));
267 * Yes, let it cat the PPD file...
270 if (execl(line
, scheme
, "cat", name
, (char *)NULL
))
273 * Unable to execute driver...
276 fprintf(stderr
, "ERROR: [cups-driverd] Unable to execute \"%s\" - %s\n",
277 line
, strerror(errno
));
284 * Static PPD, see if we have a valid path and it exists...
287 cups_file_t
*fp
; /* PPD file */
288 const char *datadir
; /* CUPS_DATADIR env var */
291 if (name
[0] == '/' || strstr(name
, "../") || strstr(name
, "/.."))
297 fprintf(stderr
, "ERROR: [cups-driverd] Bad PPD name \"%s\"!\n", name
);
302 * Try opening the file...
305 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
306 datadir
= CUPS_DATADIR
;
308 snprintf(line
, sizeof(line
), "%s/model/%s", datadir
, name
);
309 if ((fp
= cupsFileOpen(line
, "r")) == NULL
)
311 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n",
312 line
, strerror(errno
));
317 * Now copy the file to stdout...
320 while (cupsFileGets(fp
, line
, sizeof(line
)))
327 * Return with no errors...
335 * 'compare_names()' - Compare PPD filenames for sorting.
338 static int /* O - Result of comparison */
339 compare_names(const ppd_info_t
*p0
, /* I - First PPD file */
340 const ppd_info_t
*p1
) /* I - Second PPD file */
342 return (strcasecmp(p0
->record
.name
, p1
->record
.name
));
347 * 'compare_ppds()' - Compare PPD file make and model names for sorting.
350 static int /* O - Result of comparison */
351 compare_ppds(const ppd_info_t
*p0
, /* I - First PPD file */
352 const ppd_info_t
*p1
) /* I - Second PPD file */
354 int diff
; /* Difference between strings */
358 * First compare manufacturers...
361 if ((diff
= strcasecmp(p0
->record
.make
, p1
->record
.make
)) != 0)
363 else if ((diff
= cupsdCompareNames(p0
->record
.make_and_model
,
364 p1
->record
.make_and_model
)) != 0)
367 return (strcasecmp(p0
->record
.natural_language
,
368 p1
->record
.natural_language
));
373 * 'list_ppds()' - List PPD files.
376 static int /* O - Exit code */
377 list_ppds(int request_id
, /* I - Request ID */
378 int limit
, /* I - Limit */
379 const char *opt
) /* I - Option argument */
381 int i
; /* Looping var */
382 int count
; /* Number of PPDs to send */
383 ppd_info_t
*ppd
; /* Current PPD file */
384 cups_file_t
*fp
; /* ppds.dat file */
385 struct stat fileinfo
; /* ppds.dat information */
386 char filename
[1024], /* ppds.dat filename */
387 model
[1024]; /* Model directory */
388 const char *cups_cachedir
; /* CUPS_CACHEDIR environment variable */
389 const char *cups_datadir
; /* CUPS_DATADIR environment variable */
390 int num_options
; /* Number of options */
391 cups_option_t
*options
; /* Options */
392 const char *requested
, /* requested-attributes option */
393 *make
; /* ppd-make option */
394 int send_natural_language
, /* Send ppd-natural-language attribute? */
395 send_make
, /* Send ppd-make attribute? */
396 send_make_and_model
, /* Send ppd-make-and-model attribute? */
397 send_name
, /* Send ppd-name attribute? */
398 send_device_id
; /* Send ppd-device-id attribute? */
401 fprintf(stderr
, "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, opt=\"%s\"\n",
402 request_id
, limit
, opt
);
405 * See if we a PPD database file...
410 PPDs
= (ppd_info_t
*)NULL
;
413 if ((cups_cachedir
= getenv("CUPS_CACHEDIR")) == NULL
)
414 cups_cachedir
= CUPS_CACHEDIR
;
416 snprintf(filename
, sizeof(filename
), "%s/ppds.dat", cups_cachedir
);
417 if (!stat(filename
, &fileinfo
) &&
418 (fileinfo
.st_size
% sizeof(ppd_rec_t
)) == 0 &&
419 (NumPPDs
= fileinfo
.st_size
/ sizeof(ppd_rec_t
)) > 0)
422 * We have a ppds.dat file, so read it!
427 if ((PPDs
= malloc(sizeof(ppd_info_t
) * NumPPDs
)) == NULL
)
430 "ERROR: [cups-driverd] Unable to allocate memory for %d "
431 "PPD files!\n", NumPPDs
);
435 else if ((fp
= cupsFileOpen(filename
, "r")) != NULL
)
437 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
439 cupsFileRead(fp
, (char *)&(ppd
->record
), sizeof(ppd_rec_t
));
445 fprintf(stderr
, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n",
450 fprintf(stderr
, "ERROR: [cups-driverd] Unable to read \"%s\" - %s\n", filename
,
457 * Load all PPDs in the specified directory and below...
460 SortedPPDs
= NumPPDs
;
462 if ((cups_datadir
= getenv("CUPS_DATADIR")) == NULL
)
463 cups_datadir
= CUPS_DATADIR
;
465 snprintf(model
, sizeof(model
), "%s/model", cups_datadir
);
466 load_ppds(model
, "");
469 * Cull PPD files that are no longer present...
472 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
476 * Remove this PPD file from the list...
480 memmove(ppd
, ppd
+ 1, (i
- 1) * sizeof(ppd_info_t
));
487 * Sort the PPDs by name...
491 qsort(PPDs
, NumPPDs
, sizeof(ppd_info_t
),
492 (int (*)(const void *, const void *))compare_names
);
495 * Write the new ppds.dat file...
500 if ((fp
= cupsFileOpen(filename
, "w")) != NULL
)
502 for (i
= NumPPDs
, ppd
= PPDs
; i
> 0; i
--, ppd
++)
503 cupsFileWrite(fp
, (char *)&(ppd
->record
), sizeof(ppd_rec_t
));
507 fprintf(stderr
, "INFO: [cups-driverd] Wrote \"%s\", %d PPDs...\n",
511 fprintf(stderr
, "ERROR: [cups-driverd] Unable to write \"%s\" - %s\n",
512 filename
, strerror(errno
));
515 fputs("INFO: [cups-driverd] No new or changed PPDs...\n", stderr
);
518 * Scan for dynamic PPD files...
524 * Add the raw driver...
527 add_ppd("raw", "en", "Raw", "Raw Queue", "", 0, 0);
530 * Sort the PPDs by make and model...
534 qsort(PPDs
, NumPPDs
, sizeof(ppd_info_t
),
535 (int (*)(const void *, const void *))compare_ppds
);
538 * Send IPP attributes...
541 num_options
= cupsParseOptions(opt
, 0, &options
);
542 requested
= cupsGetOption("requested-attributes", num_options
, options
);
543 make
= cupsGetOption("ppd-make", num_options
, options
);
545 fprintf(stderr
, "DEBUG: [cups-driverd] requested=\"%s\"\n",
546 requested
? requested
: "(nil)");
548 if (!requested
|| strstr(requested
, "all"))
552 send_make_and_model
= 1;
553 send_natural_language
= 1;
558 send_name
= strstr(requested
, "ppd-name") != NULL
;
559 send_make
= strstr(requested
, "ppd-make,") != NULL
||
560 strstr(requested
, ",ppd-make") != NULL
||
561 !strcmp(requested
, "ppd-make");
562 send_make_and_model
= strstr(requested
, "ppd-make-and-model") != NULL
;
563 send_natural_language
= strstr(requested
, "ppd-natural-language") != NULL
;
564 send_device_id
= strstr(requested
, "ppd-device-id") != NULL
;
567 puts("Content-Type: application/ipp\n");
569 cupsdSendIPPHeader(IPP_OK
, request_id
);
570 cupsdSendIPPGroup(IPP_TAG_OPERATION
);
571 cupsdSendIPPString(IPP_TAG_CHARSET
, "attributes-charset", "utf-8");
572 cupsdSendIPPString(IPP_TAG_LANGUAGE
, "attributes-natural-language", "en-US");
574 if (limit
<= 0 || limit
> NumPPDs
)
579 for (i
= NumPPDs
, ppd
= PPDs
; count
> 0 && i
> 0; i
--, ppd
++)
580 if (!make
|| !strcasecmp(ppd
->record
.make
, make
))
586 fprintf(stderr
, "DEBUG: [cups-driverd] Sending %s (%s)...\n",
587 ppd
->record
.name
, ppd
->record
.make_and_model
);
591 cupsdSendIPPGroup(IPP_TAG_PRINTER
);
594 cupsdSendIPPString(IPP_TAG_NAME
, "ppd-name", ppd
->record
.name
);
596 if (send_natural_language
)
597 cupsdSendIPPString(IPP_TAG_LANGUAGE
, "ppd-natural-language",
598 ppd
->record
.natural_language
);
601 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-make", ppd
->record
.make
);
603 if (send_make_and_model
)
604 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-make-and-model",
605 ppd
->record
.make_and_model
);
608 cupsdSendIPPString(IPP_TAG_TEXT
, "ppd-device-id",
609 ppd
->record
.device_id
);
612 * If we have only requested the ppd-make attribute, then skip
613 * the remaining PPDs with this make...
616 if (requested
&& !strcmp(requested
, "ppd-make"))
618 const char *this_make
; /* This ppd-make */
621 for (this_make
= ppd
->record
.make
, i
--, ppd
++; i
> 0; i
--, ppd
++)
622 if (strcasecmp(this_make
, ppd
->record
.make
))
630 cupsdSendIPPTrailer();
637 * 'load_ppds()' - Load PPD files recursively.
640 static int /* O - 1 on success, 0 on failure */
641 load_ppds(const char *d
, /* I - Actual directory */
642 const char *p
) /* I - Virtual path in name */
644 int i
; /* Looping var */
645 cups_file_t
*fp
; /* Pointer to file */
646 cups_dir_t
*dir
; /* Directory pointer */
647 cups_dentry_t
*dent
; /* Directory entry */
648 char filename
[1024], /* Name of PPD or directory */
649 line
[256], /* Line from backend */
650 *ptr
, /* Pointer into name */
651 name
[128], /* Name of PPD file */
652 lang_version
[64], /* PPD LanguageVersion */
653 lang_encoding
[64], /* PPD LanguageEncoding */
654 country
[64], /* Country code */
655 manufacturer
[256], /* Manufacturer */
656 make_model
[256], /* Make and Model */
657 model_name
[256], /* ModelName */
658 nick_name
[256], /* NickName */
659 device_id
[256]; /* 1284DeviceID */
660 ppd_info_t
*ppd
, /* New PPD file */
661 key
; /* Search key */
662 int new_ppd
; /* Is this a new PPD? */
663 struct /* LanguageVersion translation table */
665 const char *version
, /* LanguageVersion string */
666 *language
; /* Language code */
678 { "japanese", "jp" },
679 { "norwegian", "no" },
681 { "portuguese", "pt" },
690 if ((dir
= cupsDirOpen(d
)) == NULL
)
692 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n",
697 while ((dent
= cupsDirRead(dir
)) != NULL
)
700 * Skip files/directories starting with "."...
703 if (dent
->filename
[0] == '.')
707 * See if this is a file...
710 snprintf(filename
, sizeof(filename
), "%s/%s", d
, dent
->filename
);
713 snprintf(name
, sizeof(name
), "%s/%s", p
, dent
->filename
);
715 strlcpy(name
, dent
->filename
, sizeof(name
));
717 if (S_ISDIR(dent
->fileinfo
.st_mode
))
723 if (!load_ppds(filename
, name
))
733 * See if this file has been scanned before...
738 strcpy(key
.record
.name
, name
);
740 ppd
= bsearch(&key
, PPDs
, SortedPPDs
, sizeof(ppd_info_t
),
741 (int (*)(const void *, const void *))compare_names
);
744 ppd
->record
.size
== dent
->fileinfo
.st_size
&&
745 ppd
->record
.mtime
== dent
->fileinfo
.st_mtime
)
755 * No, file is new/changed, so re-scan it...
758 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
762 * Now see if this is a PPD file...
766 cupsFileGets(fp
, line
, sizeof(line
));
768 if (strncmp(line
, "*PPD-Adobe:", 11))
771 * Nope, close the file and continue...
780 * Now read until we get the NickName field...
783 model_name
[0] = '\0';
785 manufacturer
[0] = '\0';
787 lang_encoding
[0] = '\0';
788 strcpy(lang_version
, "en");
790 while (cupsFileGets(fp
, line
, sizeof(line
)) != NULL
)
792 if (!strncmp(line
, "*Manufacturer:", 14))
793 sscanf(line
, "%*[^\"]\"%255[^\"]", manufacturer
);
794 else if (!strncmp(line
, "*ModelName:", 11))
795 sscanf(line
, "%*[^\"]\"%127[^\"]", model_name
);
796 else if (!strncmp(line
, "*LanguageEncoding:", 18))
797 sscanf(line
, "%*[^:]:%63s", lang_encoding
);
798 else if (!strncmp(line
, "*LanguageVersion:", 17))
799 sscanf(line
, "%*[^:]:%63s", lang_version
);
800 else if (!strncmp(line
, "*NickName:", 10))
801 sscanf(line
, "%*[^\"]\"%255[^\"]", nick_name
);
802 else if (!strncasecmp(line
, "*1284DeviceID:", 14))
803 sscanf(line
, "%*[^\"]\"%255[^\"]", device_id
);
804 else if (!strncmp(line
, "*OpenUI", 7))
807 * Stop early if we have a NickName or ModelName attributes
808 * before the first OpenUI...
811 if (model_name
[0] || nick_name
[0])
823 * See if we got all of the required info...
827 cupsCharsetToUTF8((cups_utf8_t
*)make_model
, nick_name
,
828 sizeof(make_model
), _ppdGetEncoding(lang_encoding
));
830 strcpy(make_model
, model_name
);
832 while (isspace(make_model
[0] & 255))
833 _cups_strcpy(make_model
, make_model
+ 1);
836 continue; /* Nope... */
839 * See if we got a manufacturer...
842 while (isspace(manufacturer
[0] & 255))
843 _cups_strcpy(manufacturer
, manufacturer
+ 1);
845 if (!manufacturer
[0] || !strcmp(manufacturer
, "ESP"))
848 * Nope, copy the first part of the make and model then...
851 strlcpy(manufacturer
, make_model
, sizeof(manufacturer
));
854 * Truncate at the first space, dash, or slash, or make the
855 * manufacturer "Other"...
858 for (ptr
= manufacturer
; *ptr
; ptr
++)
859 if (*ptr
== ' ' || *ptr
== '-' || *ptr
== '/')
862 if (*ptr
&& ptr
> manufacturer
)
864 else if (!strncasecmp(manufacturer
, "agfa", 4))
865 strcpy(manufacturer
, "AGFA");
866 else if (!strncasecmp(manufacturer
, "herk", 4) ||
867 !strncasecmp(manufacturer
, "linotype", 8))
868 strcpy(manufacturer
, "LHAG");
870 strcpy(manufacturer
, "Other");
873 * Hack for various vendors...
876 if (!strcasecmp(manufacturer
, "XPrint"))
877 strcpy(manufacturer
, "Xerox");
878 else if (!strcasecmp(manufacturer
, "Eastman"))
879 strcpy(manufacturer
, "Kodak");
880 else if (!strcasecmp(manufacturer
, "laserwriter"))
881 strcpy(manufacturer
, "Apple");
882 else if (!strcasecmp(manufacturer
, "colorpoint"))
883 strcpy(manufacturer
, "Seiko");
884 else if (!strcasecmp(manufacturer
, "fiery"))
885 strcpy(manufacturer
, "EFI");
886 else if (!strcasecmp(manufacturer
, "ps") ||
887 !strcasecmp(manufacturer
, "colorpass"))
888 strcpy(manufacturer
, "Canon");
889 else if (!strncasecmp(manufacturer
, "primera", 7))
890 strcpy(manufacturer
, "Fargo");
891 else if (!strcasecmp(manufacturer
, "designjet"))
892 strcpy(manufacturer
, "HP");
894 else if (!strncasecmp(manufacturer
, "LHAG", 4) ||
895 !strncasecmp(manufacturer
, "linotype", 8))
896 strcpy(manufacturer
, "LHAG");
899 * Fix the lang_version as needed...
902 if ((ptr
= strchr(lang_version
, '-')) != NULL
)
904 else if ((ptr
= strchr(lang_version
, '_')) != NULL
)
910 * Setup the country suffix...
914 _cups_strcpy(country
+ 1, ptr
);
919 * No country suffix...
925 for (i
= 0; i
< (int)(sizeof(languages
) / sizeof(languages
[0])); i
++)
926 if (!strcasecmp(languages
[i
].version
, lang_version
))
929 if (i
< (int)(sizeof(languages
) / sizeof(languages
[0])))
932 * Found a known language...
935 snprintf(lang_version
, sizeof(lang_version
), "%s%s",
936 languages
[i
].language
, country
);
941 * Unknown language; use "xx"...
944 strcpy(lang_version
, "xx");
948 * Add the PPD file...
956 * Add new PPD file...
959 fprintf(stderr
, "DEBUG: [cups-driverd] Adding ppd \"%s\"...\n", name
);
961 if (!add_ppd(name
, lang_version
, manufacturer
, make_model
, device_id
,
962 dent
->fileinfo
.st_mtime
, dent
->fileinfo
.st_size
))
971 * Update existing record...
974 fprintf(stderr
, "DEBUG: [cups-driverd] Updating ppd \"%s\"...\n", name
);
976 memset(ppd
, 0, sizeof(ppd_info_t
));
979 ppd
->record
.mtime
= dent
->fileinfo
.st_mtime
;
980 ppd
->record
.size
= dent
->fileinfo
.st_size
;
982 strlcpy(ppd
->record
.name
, name
, sizeof(ppd
->record
.name
));
983 strlcpy(ppd
->record
.make
, manufacturer
, sizeof(ppd
->record
.make
));
984 strlcpy(ppd
->record
.make_and_model
, make_model
,
985 sizeof(ppd
->record
.make_and_model
));
986 strlcpy(ppd
->record
.natural_language
, lang_version
,
987 sizeof(ppd
->record
.natural_language
));
988 strlcpy(ppd
->record
.device_id
, device_id
, sizeof(ppd
->record
.device_id
));
1001 * 'load_drivers()' - Load driver-generated PPD files.
1004 static int /* O - 1 on success, 0 on failure */
1007 const char *server_bin
; /* CUPS_SERVERBIN environment variable */
1008 char drivers
[1024]; /* Location of driver programs */
1009 FILE *fp
; /* Pipe to driver program */
1010 cups_dir_t
*dir
; /* Directory pointer */
1011 cups_dentry_t
*dent
; /* Directory entry */
1012 char filename
[1024], /* Name of driver */
1013 line
[2048], /* Line from driver */
1014 name
[512], /* ppd-name */
1015 natural_language
[128], /* ppd-natural-language */
1016 make
[128], /* ppd-make */
1017 make_and_model
[256], /* ppd-make-and-model */
1018 device_id
[256]; /* ppd-device-id */
1022 * Try opening the driver directory...
1025 if ((server_bin
= getenv("CUPS_SERVERBIN")) == NULL
)
1026 server_bin
= CUPS_SERVERBIN
;
1028 snprintf(drivers
, sizeof(drivers
), "%s/driver", server_bin
);
1030 if ((dir
= cupsDirOpen(drivers
)) == NULL
)
1032 fprintf(stderr
, "ERROR: [cups-driverd] Unable to open driver directory "
1034 drivers
, strerror(errno
));
1039 * Loop through all of the device drivers...
1042 while ((dent
= cupsDirRead(dir
)) != NULL
)
1045 * Only look at executable files...
1048 if (!(dent
->fileinfo
.st_mode
& 0111) || !S_ISREG(dent
->fileinfo
.st_mode
))
1052 * Run the driver with no arguments and collect the output...
1055 snprintf(filename
, sizeof(filename
), "%s/%s list", drivers
, dent
->filename
);
1056 if ((fp
= popen(filename
, "r")) != NULL
)
1058 while (fgets(line
, sizeof(line
), fp
) != NULL
)
1061 * Each line is of the form:
1063 * \"ppd-name\" ppd-natural-language "ppd-make" "ppd-make-and-model"
1066 device_id
[0] = '\0';
1068 if (sscanf(line
, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\""
1069 "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\"",
1070 name
, natural_language
, make
, make_and_model
,
1074 * Bad format; strip trailing newline and write an error message.
1077 if (line
[strlen(line
) - 1] == '\n')
1078 line
[strlen(line
) - 1] = '\0';
1080 fprintf(stderr
, "ERROR: [cups-driverd] Bad line from \"%s\": %s\n",
1081 dent
->filename
, line
);
1087 * Add the device to the array of available devices...
1090 if (!add_ppd(name
, natural_language
, make
, make_and_model
, device_id
,
1097 fprintf(stderr
, "DEBUG: [cups-driverd] Added dynamic PPD \"%s\"...\n",
1105 fprintf(stderr
, "WARNING: [cups-driverd] Unable to execute \"%s\": %s\n",
1106 filename
, strerror(errno
));