| // |
| // "$Id$" |
| // |
| // DDK driver interface main entry for the CUPS PPD Compiler. |
| // |
| // Copyright 2007-2008 by Apple Inc. |
| // Copyright 2002-2006 by Easy Software Products. |
| // |
| // These coded instructions, statements, and computer programs are the |
| // property of Apple Inc. and are protected by Federal copyright |
| // law. Distribution and use rights are outlined in the file "LICENSE.txt" |
| // which should have been included with this file. If this file is |
| // file is missing or damaged, see the license at "http://www.cups.org/". |
| // |
| // Contents: |
| // |
| // main() - Enumerate or display PPD files. |
| // cat_ppd() - Display a PPD file. |
| // list_ppds() - List PPDs. |
| // |
| |
| // |
| // Include necessary headers... |
| // |
| |
| #include "ppdc.h" |
| #include <cups/cups.h> |
| #include <cups/dir.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| |
| |
| // |
| // Local functions... |
| // |
| |
| static int cat_ppd(ppdcSource *src, const char *name); |
| static int list_drvs(const char *pathname, const char *prefix); |
| static int list_ppds(ppdcSource *src, const char *name); |
| |
| |
| // |
| // 'main()' - Enumerate or display PPD files. |
| // |
| |
| int // O - Exit status |
| main(int argc, // I - Number of command-line arguments |
| char *argv[]) // I - Command-line arguments |
| { |
| const char *datadir; // CUPS_DATADIR |
| ppdcSource *src; // PPD source file data |
| char filename[1024], // Full path to .drv file(s) |
| scheme[32], // URI scheme ("drv") |
| userpass[256], // User/password info (unused) |
| host[2], // Hostname (unused) |
| resource[1024], // Resource path (/dir/to/filename.drv) |
| *pc_file_name; // Filename portion of URI |
| int port, // Port number (unused) |
| status; // Exit status |
| |
| |
| // Determine where CUPS has installed the data files... |
| if ((datadir = getenv("CUPS_DATADIR")) == NULL) |
| datadir = CUPS_DATADIR; |
| |
| // List all available PPDs or cat a single PPD... |
| if (argc == 2 && !strcmp(argv[1], "list")) |
| { |
| #ifdef __APPLE__ |
| if (!access("/Library/Printers/PPDs.drv", 0)) |
| list_drvs("/Library/Printers/PPDs.drv", "/Library/Printers/PPDs.drv"); |
| #endif // __APPLE__ |
| |
| snprintf(filename, sizeof(filename), "%s/drv", datadir); |
| return (list_drvs(filename, "/")); |
| } |
| else if (argc == 3 && !strcmp(argv[1], "cat")) |
| { |
| httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme, sizeof(scheme), |
| userpass, sizeof(userpass), host, sizeof(host), &port, |
| resource, sizeof(resource)); |
| |
| if (strstr(resource, "../") || |
| (pc_file_name = strrchr(resource, '/')) == NULL || |
| pc_file_name == resource) |
| { |
| fprintf(stderr, "ERROR: Bad driver info URI \"%s\"!\n", argv[2]); |
| return (1); |
| } |
| |
| *pc_file_name++ = '\0'; |
| |
| #ifdef __APPLE__ |
| if (!strncmp(resource, "/Library/Printers/PPDs.drv/", 27)) |
| strlcpy(filename, resource, sizeof(filename)); |
| else |
| #endif // __APPLE__ |
| |
| snprintf(filename, sizeof(filename), "%s/drv%s", datadir, resource); |
| |
| src = new ppdcSource(filename); |
| |
| status = cat_ppd(src, pc_file_name); |
| |
| delete src; |
| |
| return (status); |
| } |
| |
| fprintf(stderr, "ERROR: Usage: %s cat URI\n", argv[0]); |
| fprintf(stderr, "ERROR: Usage: %s list\n", argv[0]); |
| |
| return (1); |
| } |
| |
| |
| // |
| // 'cat_ppd()' - Display a PPD file. |
| // |
| |
| static int // O - Exit status |
| cat_ppd(ppdcSource *src, // I - Driver info file |
| const char *name) // I - PC filename |
| { |
| ppdcDriver *d; // Current driver |
| cups_file_t *out; // Stdout via CUPS file API |
| |
| |
| for (d = (ppdcDriver *)src->drivers->first(); |
| d; |
| d = (ppdcDriver *)src->drivers->next()) |
| if (!strcmp(name, d->pc_file_name->value)) |
| { |
| out = cupsFileStdout(); |
| |
| d->write_ppd_file(out, NULL, NULL, src, PPDC_LFONLY); |
| cupsFileClose(out); |
| return (0); |
| } |
| |
| return (1); |
| } |
| |
| |
| // |
| // 'list_drvs()' - List all drv files in the given path... |
| // |
| |
| static int // O - Exit status |
| list_drvs(const char *pathname, // I - Full path to directory |
| const char *prefix) // I - Prefix for directory |
| { |
| char *ext, // Extension on file |
| filename[1024], // Full path to .drv file(s) |
| newprefix[1024]; // New prefix for directory |
| cups_dir_t *dir; // Current directory |
| cups_dentry_t *dent; // Current directory entry |
| |
| |
| if ((dir = cupsDirOpen(pathname)) == NULL) |
| return (1); |
| |
| while ((dent = cupsDirRead(dir)) != NULL) |
| { |
| // Skip "dot" files... |
| if (dent->filename[0] == '.') |
| continue; |
| |
| // See if this is a file or directory... |
| snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename); |
| |
| if (S_ISDIR(dent->fileinfo.st_mode)) |
| { |
| // Descend into the subdirectory... |
| snprintf(newprefix, sizeof(newprefix), "%s%s/", prefix, dent->filename); |
| |
| if (list_drvs(filename, newprefix)) |
| { |
| cupsDirClose(dir); |
| return (1); |
| } |
| } |
| else if ((ext = strrchr(dent->filename, '.')) != NULL && |
| (!strcmp(ext, ".drv") || !strcmp(ext, ".drv.gz"))) |
| { |
| // List the PPDs in this driver info file... |
| ppdcSource *src = new ppdcSource(filename); |
| // Driver info file |
| |
| snprintf(newprefix, sizeof(newprefix), "%s%s", prefix, dent->filename); |
| list_ppds(src, newprefix); |
| delete src; |
| } |
| } |
| |
| cupsDirClose(dir); |
| |
| return (0); |
| } |
| |
| |
| // |
| // 'list_ppds()' - List PPDs in a driver info file. |
| // |
| |
| static int // O - Exit status |
| list_ppds(ppdcSource *src, // I - Driver info file |
| const char *name) // I - Name of driver info file |
| { |
| ppdcDriver *d; // Current driver |
| ppdcAttr *attr; // 1284DeviceID attribute |
| char uri[1024]; // Driver URI |
| |
| |
| for (d = (ppdcDriver *)src->drivers->first(); |
| d; |
| d = (ppdcDriver *)src->drivers->next()) |
| { |
| httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "drv", "", "", 0, |
| "%s/%s", name, d->pc_file_name->value); |
| |
| attr = d->find_attr("1284DeviceID", NULL); |
| |
| printf("\"%s\" en \"%s\" \"%s\" \"%s\"\n", uri, d->manufacturer->value, |
| d->model_name->value, attr ? attr->value->value : ""); |
| } |
| |
| return (0); |
| } |
| |
| |
| |
| |
| #if 0 |
| |
| |
| |
| // Scan the command-line... |
| catalog = NULL; |
| outdir = "ppd"; |
| src = 0; |
| verbose = 0; |
| locales = NULL; |
| comp = PPDC_NO_COMPRESSION; |
| le = PPDC_LFONLY; |
| |
| for (i = 1; i < argc; i ++) |
| if (argv[i][0] == '-') |
| { |
| for (opt = argv[i] + 1; *opt; opt ++) |
| switch (*opt) |
| { |
| case 'c' : // Message catalog... |
| i ++; |
| if (i >= argc) |
| usage(); |
| |
| if (verbose > 1) |
| printf("ppdc: Loading messages from \"%s\"...\n", argv[i]); |
| |
| if (!catalog) |
| catalog = new ppdcCatalog("en"); |
| |
| if (catalog->load_messages(argv[i])) |
| { |
| fprintf(stderr, |
| "ppdc: Unable to load localization file \"%s\" - %s\n", |
| argv[i], strerror(errno)); |
| return (1); |
| } |
| break; |
| |
| case 'd' : // Output directory... |
| i ++; |
| if (i >= argc) |
| usage(); |
| |
| if (verbose > 1) |
| printf("ppdc: Writing PPD files to directory \"%s\"...\n", |
| argv[i]); |
| |
| outdir = argv[i]; |
| break; |
| |
| case 'l' : // Language(s)... |
| i ++; |
| if (i >= argc) |
| usage(); |
| |
| if (strchr(argv[i], ',')) |
| { |
| // Comma-delimited list of languages... |
| char temp[1024], // Copy of language list |
| *start, // Start of current locale name |
| *end; // End of current locale name |
| |
| |
| locales = new ppdcArray(); |
| |
| strlcpy(temp, argv[i], sizeof(temp)); |
| for (start = temp; *start; start = end) |
| { |
| if ((end = strchr(start, ',')) != NULL) |
| *end++ = '\0'; |
| else |
| end = start + strlen(start); |
| |
| if (end > start) |
| locales->add(new ppdcString(start)); |
| } |
| } |
| else |
| { |
| if (verbose > 1) |
| printf("ppdc: Loading messages for locale \"%s\"...\n", |
| argv[i]); |
| |
| if (catalog) |
| delete catalog; |
| |
| catalog = new ppdcCatalog(argv[i]); |
| |
| if (catalog->messages->count == 0) |
| { |
| fprintf(stderr, |
| "ppdc: Unable to find localization for \"%s\" - %s\n", |
| argv[i], strerror(errno)); |
| return (1); |
| } |
| } |
| break; |
| |
| case 'I' : // Include directory... |
| i ++; |
| if (i >= argc) |
| usage(); |
| |
| if (verbose > 1) |
| printf("ppdc: Adding include directory \"%s\"...\n", argv[i]); |
| |
| ppdcSource::add_include(argv[i]); |
| break; |
| |
| case 'v' : // Be verbose... |
| verbose ++; |
| break; |
| |
| case 'z' : // Compress files... |
| comp = PPDC_GZIP_COMPRESSION; |
| break; |
| |
| case '-' : // --option |
| if (!strcmp(opt, "-lf")) |
| { |
| le = PPDC_LFONLY; |
| opt += strlen(opt) - 1; |
| break; |
| } |
| else if (!strcmp(opt, "-cr")) |
| { |
| le = PPDC_CRONLY; |
| opt += strlen(opt) - 1; |
| break; |
| } |
| else if (!strcmp(opt, "-crlf")) |
| { |
| le = PPDC_CRLF; |
| opt += strlen(opt) - 1; |
| break; |
| } |
| |
| default : // Unknown |
| usage(); |
| break; |
| } |
| } |
| else |
| { |
| // Open and load the driver info file... |
| if (verbose > 1) |
| printf("ppdc: Loading driver information file \"%s\"...\n", argv[i]); |
| |
| src = new ppdcSource(argv[i]); |
| |
| // Create the output directory... |
| if (mkdir(outdir, 0777)) |
| { |
| if (errno != EEXIST) |
| { |
| fprintf(stderr, "ppdc: Unable to create output directory %s: %s\n", |
| outdir, strerror(errno)); |
| return (1); |
| } |
| } |
| |
| // Write PPD files... |
| for (d = (ppdcDriver *)src->drivers->first(); |
| d; |
| d = (ppdcDriver *)src->drivers->next()) |
| { |
| // Write the PPD file for this driver... |
| for (j = 0; d->pc_file_name->value[j]; j ++) |
| pcfilename[j] = tolower(d->pc_file_name->value[j]); |
| |
| pcfilename[j] = '\0'; |
| |
| if (comp == PPDC_GZIP_COMPRESSION) |
| snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename); |
| else |
| snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename); |
| |
| if (verbose) |
| printf("ppdc: Writing %s...\n", filename); |
| |
| if (d->write_ppd_file(filename, catalog, locales, src, le, comp)) |
| return (1); |
| } |
| |
| // Delete the printer driver information... |
| delete src; |
| } |
| |
| if (catalog) |
| delete catalog; |
| |
| // If no drivers have been loaded, display the program usage message. |
| if (!src) |
| usage(); |
| |
| // Return with no errors. |
| return (0); |
| } |
| #endif // 0 |
| |
| |
| // |
| // End of "$Id$". |
| // |