diff -up cups-1.3.8/berkeley/lpr.c.getnameddest cups-1.3.8/berkeley/lpr.c --- cups-1.3.8/berkeley/lpr.c.getnameddest 2008-07-28 16:28:24.000000000 +0100 +++ cups-1.3.8/berkeley/lpr.c 2008-07-28 16:28:24.000000000 +0100 @@ -92,9 +92,7 @@ main(int argc, /* I - Number of comm int num_copies; /* Number of copies per file */ int num_files; /* Number of files to print */ const char *files[1000]; /* Files to print */ - int num_dests; /* Number of destinations */ - cups_dest_t *dests, /* Destinations */ - *dest; /* Selected destination */ + cups_dest_t *dest; /* Selected destination */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ int deletefile; /* Delete file after print? */ @@ -112,8 +110,7 @@ main(int argc, /* I - Number of comm deletefile = 0; printer = NULL; - num_dests = 0; - dests = NULL; + dest = NULL; num_options = 0; options = NULL; num_files = 0; @@ -282,10 +279,7 @@ main(int argc, /* I - Number of comm if ((instance = strrchr(printer, '/')) != NULL) *instance++ = '\0'; - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) + if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL) { for (j = 0; j < dest->num_options; j ++) if (cupsGetOption(dest->options[j].name, num_options, @@ -385,10 +379,7 @@ main(int argc, /* I - Number of comm if (printer == NULL) { - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) + if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) { printer = dest->name; @@ -417,7 +408,7 @@ main(int argc, /* I - Number of comm else val = "LPDEST"; - if (printer && !cupsGetDest(printer, NULL, num_dests, dests)) + if (printer && !cupsGetNamedDest(NULL, printer, NULL)) _cupsLangPrintf(stderr, _("%s: Error - %s environment variable names " "non-existent destination \"%s\"!\n"), diff -up cups-1.3.8/cups/cups.h.getnameddest cups-1.3.8/cups/cups.h --- cups-1.3.8/cups/cups.h.getnameddest 2008-07-11 23:48:49.000000000 +0100 +++ cups-1.3.8/cups/cups.h 2008-07-28 16:28:24.000000000 +0100 @@ -248,6 +248,9 @@ extern void cupsSetDefaultDest(const ch int num_dests, cups_dest_t *dests); +/**** New in CUPS 1.4 ****/ +extern cups_dest_t *cupsGetNamedDest(http_t *http, const char *name, + const char *instance); # ifdef __cplusplus } diff -up cups-1.3.8/cups/dest.c.getnameddest cups-1.3.8/cups/dest.c --- cups-1.3.8/cups/dest.c.getnameddest 2008-07-11 23:48:49.000000000 +0100 +++ cups-1.3.8/cups/dest.c 2008-07-28 16:28:24.000000000 +0100 @@ -25,6 +25,7 @@ * server. * cupsGetDests2() - Get the list of destinations from the * specified server. + * cupsGetNamedDest() - Get options for the named destination. * cupsRemoveDest() - Remove a destination from the destination list. * cupsDestSetDefaultDest() - Set the default destination. * cupsSetDests() - Set the list of destinations for the default @@ -39,6 +40,7 @@ * Include necessary headers... */ +#include "debug.h" #include "globals.h" #include #include @@ -53,10 +55,13 @@ * Local functions... */ -static int cups_get_dests(const char *filename, int num_dests, +static const char *cups_get_default(const char *filename, char *namebuf, + size_t namesize, const char **instance); +static int cups_get_dests(const char *filename, const char *match_name, + const char *match_inst, int num_dests, cups_dest_t **dests); -static int cups_get_sdests(http_t *http, ipp_op_t op, int num_dests, - cups_dest_t **dests); +static int cups_get_sdests(http_t *http, ipp_op_t op, const char *name, + int num_dests, cups_dest_t **dests); /* @@ -263,19 +268,17 @@ int /* O - Number of destinations */ cupsGetDests(cups_dest_t **dests) /* O - Destinations */ { int num_dests; /* Number of destinations */ - http_t *http; /* HTTP connection */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * Connect to the CUPS server and get the destination list and options... */ - http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); + if (!cg->http) + cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); - num_dests = cupsGetDests2(http, dests); - - if (http) - httpClose(http); + num_dests = cupsGetDests2(cg->http, dests); return (num_dests); } @@ -330,8 +333,8 @@ cupsGetDests2(http_t *http, /* I - * Grab the printers and classes... */ - num_dests = cups_get_sdests(http, CUPS_GET_PRINTERS, num_dests, dests); - num_dests = cups_get_sdests(http, CUPS_GET_CLASSES, num_dests, dests); + num_dests = cups_get_sdests(http, CUPS_GET_PRINTERS, NULL, num_dests, dests); + num_dests = cups_get_sdests(http, CUPS_GET_CLASSES, NULL, num_dests, dests); /* * Make a copy of the "real" queues for a later sanity check... @@ -390,7 +393,7 @@ cupsGetDests2(http_t *http, /* I - */ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); - num_dests = cups_get_dests(filename, num_dests, dests); + num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests); if ((home = getenv("HOME")) != NULL) { @@ -398,7 +401,7 @@ cupsGetDests2(http_t *http, /* I - if (access(filename, 0)) snprintf(filename, sizeof(filename), "%s/.lpoptions", home); - num_dests = cups_get_dests(filename, num_dests, dests); + num_dests = cups_get_dests(filename, NULL, NULL, num_dests, dests); } /* @@ -452,6 +455,136 @@ cupsGetDests2(http_t *http, /* I - /* + * 'cupsGetNamedDest()' - Get options for the named destination. + * + * This function is optimized for retrieving a single destination and should + * be used instead of cupsGetDests() and cupsGetDest() when you either know + * the name of the destination or want to print to the default destination. + * If NULL is returned, the destination does not exist or there is no default + * destination. + * + * If "http" is NULL, the connection to the default print server will be used. + * + * If "name" is NULL, the default printer for the current user will be returned. + * + * The returned destination must be freed using cupsFreeDests() with a + * "num_dests" of 1. + * + * @since CUPS 1.4@ + */ + +cups_dest_t * /* O - Destination or NULL */ +cupsGetNamedDest(http_t *http, /* I - HTTP connection or NULL */ + const char *name, /* I - Destination name or NULL */ + const char *instance) /* I - Instance name or NULL */ +{ + cups_dest_t *dest; /* Destination */ + char filename[1024], /* Path to lpoptions */ + defname[256]; /* Default printer name */ + const char *home = getenv("HOME"); /* Home directory */ + ipp_op_t op = IPP_GET_PRINTER_ATTRIBUTES; + /* IPP operation to get server ops */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ + + + /* + * Connect to the server as needed... + */ + + if (!http) + { + if (!cg->http && + (cg->http = httpConnectEncrypt(cupsServer(), ippPort(), + cupsEncryption())) == NULL) + return (NULL); + + http = cg->http; + } + + /* + * If "name" is NULL, find the default destination... + */ + + if (!name) + { + if ((name = getenv("LPDEST")) == NULL) + if ((name = getenv("PRINTER")) != NULL && !strcmp(name, "lp")) + name = NULL; + + if (!name && home) + { + /* + * No default in the environment, try the user's lpoptions files... + */ + + snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); + + if ((name = cups_get_default(filename, defname, sizeof(defname), + &instance)) == NULL) + { + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + name = cups_get_default(filename, defname, sizeof(defname), + &instance); + } + } + + if (!name) + { + /* + * Still not there? Try the system lpoptions file... + */ + + snprintf(filename, sizeof(filename), "%s/lpoptions", + cg->cups_serverroot); + name = cups_get_default(filename, defname, sizeof(defname), &instance); + } + + if (!name) + { + /* + * No locally-set default destination, ask the server... + */ + + op = CUPS_GET_DEFAULT; + } + } + + /* + * Get the printer's attributes... + */ + + if (!cups_get_sdests(http, op, name, 0, &dest)) + return (NULL); + + if (instance) + dest->instance = _cupsStrAlloc(instance); + + /* + * Then add local options... + */ + + snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); + cups_get_dests(filename, name, instance, 1, &dest); + + if (home) + { + snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); + + if (access(filename, 0)) + snprintf(filename, sizeof(filename), "%s/.lpoptions", home); + + cups_get_dests(filename, name, instance, 1, &dest); + } + + /* + * Return the result... + */ + + return (dest); +} + + +/* * 'cupsRemoveDest()' - Remove a destination from the destination list. * * Removing a destination/instance does not delete the class or printer @@ -548,19 +681,17 @@ void cupsSetDests(int num_dests, /* I - Number of destinations */ cups_dest_t *dests) /* I - Destinations */ { - http_t *http; /* HTTP connection */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ /* * Connect to the CUPS server and save the destination list and options... */ - http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); - - cupsSetDests2(http, num_dests, dests); + if (!cg->http) + cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); - if (http) - httpClose(http); + cupsSetDests2(cg->http, num_dests, dests); } @@ -606,8 +737,8 @@ cupsSetDests2(http_t *http, /* I - * Get the server destinations... */ - num_temps = cups_get_sdests(http, CUPS_GET_PRINTERS, 0, &temps); - num_temps = cups_get_sdests(http, CUPS_GET_CLASSES, num_temps, &temps); + num_temps = cups_get_sdests(http, CUPS_GET_PRINTERS, NULL, 0, &temps); + num_temps = cups_get_sdests(http, CUPS_GET_CLASSES, NULL, num_temps, &temps); /* * Figure out which file to write to... @@ -622,7 +753,7 @@ cupsSetDests2(http_t *http, /* I - * Merge in server defaults... */ - num_temps = cups_get_dests(filename, num_temps, &temps); + num_temps = cups_get_dests(filename, NULL, NULL, num_temps, &temps); /* * Point to user defaults... @@ -789,24 +920,88 @@ cupsSetDests2(http_t *http, /* I - /* + * 'cups_get_default()' - Get the default destination from an lpoptions file. + */ + +static const char * /* O - Default destination or NULL */ +cups_get_default(const char *filename, /* I - File to read */ + char *namebuf, /* I - Name buffer */ + size_t namesize, /* I - Size of name buffer */ + const char **instance) /* I - Instance */ +{ + cups_file_t *fp; /* lpoptions file */ + char line[8192], /* Line from file */ + *value, /* Value for line */ + *nameptr; /* Pointer into name */ + int linenum; /* Current line */ + + + *namebuf = '\0'; + + if ((fp = cupsFileOpen(filename, "r")) != NULL) + { + linenum = 0; + + while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + { + if (!strcasecmp(line, "default") && value) + { + strlcpy(namebuf, value, namesize); + + if ((nameptr = strchr(namebuf, ' ')) != NULL) + *nameptr = '\0'; + if ((nameptr = strchr(namebuf, '\t')) != NULL) + *nameptr = '\0'; + + if ((nameptr = strchr(namebuf, '/')) != NULL) + *nameptr++ = '\0'; + + *instance = nameptr; + break; + } + } + + cupsFileClose(fp); + } + + return (*namebuf ? namebuf : NULL); +} + + +/* * 'cups_get_dests()' - Get destinations from a file. */ static int /* O - Number of destinations */ cups_get_dests(const char *filename, /* I - File to read from */ + const char *match_name, /* I - Destination name we want */ + const char *match_inst, /* I - Instance name we want */ int num_dests, /* I - Number of destinations */ cups_dest_t **dests) /* IO - Destinations */ { int i; /* Looping var */ cups_dest_t *dest; /* Current destination */ - FILE *fp; /* File pointer */ + cups_file_t *fp; /* File pointer */ char line[8192], /* Line from file */ *lineptr, /* Pointer into line */ *name, /* Name of destination/option */ *instance; /* Instance of destination */ + int linenum; /* Current line number */ const char *printer; /* PRINTER or LPDEST */ + DEBUG_printf(("cups_get_dests(filename=\"%s\", match_name=\"%s\", " + "match_inst=\"%s\", num_dests=%d, dests=%p)\n", filename, + match_name ? match_name : "(null)", + match_inst ? match_inst : "(null)", num_dests, dests)); + + /* + * Try to open the file... + */ + + if ((fp = cupsFileOpen(filename, "r")) == NULL) + return (num_dests); + /* * Check environment variables... */ @@ -816,12 +1011,8 @@ cups_get_dests(const char *filename, /* if (strcmp(printer, "lp") == 0) printer = NULL; - /* - * Try to open the file... - */ - - if ((fp = fopen(filename, "r")) == NULL) - return (num_dests); + DEBUG_printf(("cups_get_dests: printer=\"%s\"\n", + printer ? printer : "(null)")); /* * Read each printer; each line looks like: @@ -830,28 +1021,22 @@ cups_get_dests(const char *filename, /* * Default name[/instance] options */ - while (fgets(line, sizeof(line), fp) != NULL) + linenum = 0; + + while (cupsFileGetConf(fp, line, sizeof(line), &lineptr, &linenum)) { /* * See what type of line it is... */ - if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4] & 255)) - lineptr = line + 4; - else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7] & 255)) - lineptr = line + 7; - else - continue; - - /* - * Skip leading whitespace... - */ - - while (isspace(*lineptr & 255)) - lineptr ++; + DEBUG_printf(("cups_get_dests: linenum=%d line=\"%s\" lineptr=\"%s\"\n", + linenum, line, lineptr ? lineptr : "(null)")); - if (!*lineptr) + if ((strcasecmp(line, "dest") && strcasecmp(line, "default")) || !lineptr) + { + DEBUG_puts("cups_get_dests: Not a dest or default line..."); continue; + } name = lineptr; @@ -862,9 +1047,6 @@ cups_get_dests(const char *filename, /* while (!isspace(*lineptr & 255) && *lineptr && *lineptr != '/') lineptr ++; - if (!*lineptr) - continue; - if (*lineptr == '/') { /* @@ -884,30 +1066,49 @@ cups_get_dests(const char *filename, /* else instance = NULL; - *lineptr++ = '\0'; + if (*lineptr) + *lineptr++ = '\0'; + + DEBUG_printf(("cups_get_dests: name=\"%s\", instance=\"%s\"\n", name, + instance)); /* * See if the primary instance of the destination exists; if not, * ignore this entry and move on... */ - if (cupsGetDest(name, NULL, num_dests, *dests) == NULL) - continue; - - /* - * Add the destination... - */ - - num_dests = cupsAddDest(name, instance, num_dests, dests); + if (match_name) + { + if (strcasecmp(name, match_name) || + (!instance && match_inst) || + (instance && !match_inst) || + (instance && strcasecmp(instance, match_inst))) + continue; - if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL) + dest = *dests; + } + else if (cupsGetDest(name, NULL, num_dests, *dests) == NULL) + { + DEBUG_puts("cups_get_dests: Not found!"); + continue; + } + else { /* - * Out of memory! + * Add the destination... */ - fclose(fp); - return (num_dests); + num_dests = cupsAddDest(name, instance, num_dests, dests); + + if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL) + { + /* + * Out of memory! + */ + + DEBUG_puts("cups_get_dests: Out of memory!"); + break; + } } /* @@ -918,11 +1119,20 @@ cups_get_dests(const char *filename, /* &(dest->options)); /* + * If we found what we were looking for, stop now... + */ + + if (match_name) + break; + + /* * Set this as default if needed... */ - if (strncasecmp(line, "default", 7) == 0 && printer == NULL) + if (!printer && !strcasecmp(line, "default")) { + DEBUG_puts("cups_get_dests: Setting as default..."); + for (i = 0; i < num_dests; i ++) (*dests)[i].is_default = 0; @@ -934,7 +1144,7 @@ cups_get_dests(const char *filename, /* * Close the file and return... */ - fclose(fp); + cupsFileClose(fp); return (num_dests); } @@ -946,7 +1156,8 @@ cups_get_dests(const char *filename, /* static int /* O - Number of destinations */ cups_get_sdests(http_t *http, /* I - HTTP connection */ - ipp_op_t op, /* I - get-printers or get-classes */ + ipp_op_t op, /* I - IPP operation */ + const char *name, /* I - Name of destination */ int num_dests, /* I - Number of destinations */ cups_dest_t **dests) /* IO - Destinations */ { @@ -963,8 +1174,9 @@ cups_get_sdests(http_t *http, /* I const char *info, /* printer-info attribute */ *location, /* printer-location attribute */ *make_model, /* printer-make-and-model attribute */ - *name; /* printer-name attribute */ - char job_sheets[1024], /* job-sheets-default attribute */ + *printer_name; /* printer-name attribute */ + char uri[1024], /* printer-uri value */ + job_sheets[1024], /* job-sheets-default attribute */ auth_info_req[1024], /* auth-info-required attribute */ reasons[1024]; /* printer-state-reasons attribute */ int num_options; /* Number of options */ @@ -1008,6 +1220,14 @@ cups_get_sdests(http_t *http, /* I ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); + if (name) + { + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, + "localhost", ippPort(), "/printers/%s", name); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, + uri); + } + /* * Do the request and get back a response... */ @@ -1030,17 +1250,17 @@ cups_get_sdests(http_t *http, /* I * Pull the needed attributes from this printer... */ - accepting = 0; - change_time = 0; - info = NULL; - location = NULL; - make_model = NULL; - name = NULL; - num_options = 0; - options = NULL; - shared = 1; - state = IPP_PRINTER_IDLE; - type = CUPS_PRINTER_LOCAL; + accepting = 0; + change_time = 0; + info = NULL; + location = NULL; + make_model = NULL; + printer_name = NULL; + num_options = 0; + options = NULL; + shared = 1; + state = IPP_PRINTER_IDLE; + type = CUPS_PRINTER_LOCAL; auth_info_req[0] = '\0'; job_sheets[0] = '\0'; @@ -1091,7 +1311,7 @@ cups_get_sdests(http_t *http, /* I make_model = attr->values[0].string.text; else if (!strcmp(attr->name, "printer-name") && attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; + printer_name = attr->values[0].string.text; else if (!strcmp(attr->name, "printer-state") && attr->value_tag == IPP_TAG_ENUM) state = attr->values[0].integer; @@ -1196,7 +1416,7 @@ cups_get_sdests(http_t *http, /* I * See if we have everything needed... */ - if (!name) + if (!printer_name) { cupsFreeOptions(num_options, options); @@ -1206,9 +1426,9 @@ cups_get_sdests(http_t *http, /* I continue; } - num_dests = cupsAddDest(name, NULL, num_dests, dests); + num_dests = cupsAddDest(printer_name, NULL, num_dests, dests); - if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL) + if ((dest = cupsGetDest(printer_name, NULL, num_dests, *dests)) != NULL) { dest->num_options = num_options; dest->options = options; diff -up cups-1.3.8/cups/libcups.exp.getnameddest cups-1.3.8/cups/libcups.exp --- cups-1.3.8/cups/libcups.exp.getnameddest 2008-04-09 04:39:40.000000000 +0100 +++ cups-1.3.8/cups/libcups.exp 2008-07-28 16:28:24.000000000 +0100 @@ -114,6 +114,7 @@ _cupsGetFd _cupsGetFile _cupsGetJobs _cupsGetJobs2 +_cupsGetNamedDest _cupsGetOption _cupsGetPassword _cupsGetPPD diff -up cups-1.3.8/cups/Makefile.getnameddest cups-1.3.8/cups/Makefile --- cups-1.3.8/cups/Makefile.getnameddest 2008-02-20 20:18:33.000000000 +0000 +++ cups-1.3.8/cups/Makefile 2008-07-28 16:28:24.000000000 +0100 @@ -263,7 +263,7 @@ libcups.so.2 libcups.sl.2: $(LIBOBJS) # libcups.2.dylib # -libcups.2.dylib: $(LIBOBJS) $(LIBCUPSORDER) +libcups.2.dylib: $(LIBOBJS) $(LIBCUPSORDER) libcups.exp echo Linking $@... $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ \ -install_name $(libdir)/$@ \ diff -up cups-1.3.8/cups/testcups.c.getnameddest cups-1.3.8/cups/testcups.c --- cups-1.3.8/cups/testcups.c.getnameddest 2008-07-11 23:48:49.000000000 +0100 +++ cups-1.3.8/cups/testcups.c 2008-07-28 16:37:24.000000000 +0100 @@ -16,7 +16,8 @@ * * Contents: * - * main() - Main entry. + * main() - Main entry. + * dests_equal() - Determine whether two destinations are equal. */ /* @@ -29,6 +30,14 @@ /* + * Local functions... + */ + +static int dests_equal(cups_dest_t *a, cups_dest_t *b); +static void show_diffs(cups_dest_t *a, cups_dest_t *b); + + +/* * 'main()' - Main entry. */ @@ -37,9 +46,11 @@ main(int argc, /* I - Number of comm char *argv[]) /* I - Command-line arguments */ { int status = 0, /* Exit status */ + i, /* Looping var */ num_dests; /* Number of destinations */ cups_dest_t *dests, /* Destinations */ - *dest; /* Current destination */ + *dest, /* Current destination */ + *named_dest; /* Current named destination */ const char *ppdfile; /* PPD file */ ppd_file_t *ppd; /* PPD file data */ int num_jobs; /* Number of jobs for queue */ @@ -61,7 +72,78 @@ main(int argc, /* I - Number of comm return (1); } else - puts("PASS"); + { + printf("PASS (%d dests)\n", num_dests); + + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + { + printf(" %s", dest->name); + + if (dest->instance) + printf(" /%s", dest->instance); + + if (dest->is_default) + puts(" ***DEFAULT***"); + else + putchar('\n'); + } + } + + /* + * cupsGetDest(NULL) + */ + + fputs("cupsGetDest(NULL): ", stdout); + fflush(stdout); + + if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) + { + for (i = num_dests, dest = dests; i > 0; i --, dest ++) + if (dest->is_default) + break; + + if (i) + { + status = 1; + puts("FAIL"); + } + else + puts("PASS (no default)"); + + dest = NULL; + } + else + printf("PASS (%s)\n", dest->name); + + /* + * cupsGetNamedDest(NULL, NULL, NULL) + */ + + fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout); + fflush(stdout); + + if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL || + !dests_equal(dest, named_dest)) + { + if (!dest) + puts("PASS (no default)"); + else if (named_dest) + { + puts("FAIL (different values)"); + show_diffs(dest, named_dest); + status = 1; + } + else + { + puts("FAIL (no default)"); + status = 1; + } + } + else + printf("PASS (%s)\n", named_dest->name); + + if (named_dest) + cupsFreeDests(1, named_dest); /* * cupsGetDest(printer) @@ -79,20 +161,33 @@ main(int argc, /* I - Number of comm puts("PASS"); /* - * cupsGetDest(NULL) + * cupsGetNamedDest(NULL, printer, instance) */ - fputs("cupsGetDest(NULL): ", stdout); + printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name, + dest->instance ? dest->instance : "(null)"); fflush(stdout); - if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) + if ((named_dest = cupsGetNamedDest(NULL, dest->name, + dest->instance)) == NULL || + !dests_equal(dest, named_dest)) { - puts("FAIL"); + if (named_dest) + { + puts("FAIL (different values)"); + show_diffs(dest, named_dest); + } + else + puts("FAIL (no destination)"); + return (1); } else puts("PASS"); + if (named_dest) + cupsFreeDests(1, named_dest); + /* * cupsPrintFile() */ @@ -169,5 +264,83 @@ main(int argc, /* I - Number of comm /* + * 'dests_equal()' - Determine whether two destinations are equal. + */ + +static int /* O - 1 if equal, 0 if not equal */ +dests_equal(cups_dest_t *a, /* I - First destination */ + cups_dest_t *b) /* I - Second destination */ +{ + int i; /* Looping var */ + cups_option_t *aoption; /* Current option */ + const char *bval; /* Option value */ + + + if (a == b) + return (1); + + if ((!a && b) || (a && !b)) + return (0); + + if (strcasecmp(a->name, b->name) || + (a->instance && !b->instance) || + (!a->instance && b->instance) || + (a->instance && strcasecmp(a->instance, b->instance)) || + a->num_options != b->num_options) + return (0); + + for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++) + if ((bval = cupsGetOption(aoption->name, b->num_options, + b->options)) == NULL || + strcmp(aoption->value, bval)) + return (0); + + return (1); +} + + +/* + * 'show_diffs()' - Show differences between two destinations. + */ + +static void +show_diffs(cups_dest_t *a, /* I - First destination */ + cups_dest_t *b) /* I - Second destination */ +{ + int i; /* Looping var */ + cups_option_t *aoption; /* Current option */ + const char *bval; /* Option value */ + + + if (!a || !b) + return; + + puts(" Item cupsGetDest cupsGetNamedDest"); + puts(" -------------------- -------------------- --------------------"); + + if (strcasecmp(a->name, b->name)) + printf(" name %-20.20s %-20.20s\n", a->name, b->name); + + if ((a->instance && !b->instance) || + (!a->instance && b->instance) || + (a->instance && strcasecmp(a->instance, b->instance))) + printf(" instance %-20.20s %-20.20s\n", + a->instance ? a->instance : "(null)", + b->instance ? b->instance : "(null)"); + + if (a->num_options != b->num_options) + printf(" num_options %-20d %-20d\n", a->num_options, + b->num_options); + + for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++) + if ((bval = cupsGetOption(aoption->name, b->num_options, + b->options)) == NULL || + strcmp(aoption->value, bval)) + printf(" %-20.20s %-20.20s %-20.20s\n", aoption->name, + aoption->value, bval ? bval : "(null)"); +} + + +/* * End of "$Id: testcups.c 7721 2008-07-11 22:48:49Z mike $". */ diff -up cups-1.3.8/systemv/lp.c.getnameddest cups-1.3.8/systemv/lp.c --- cups-1.3.8/systemv/lp.c.getnameddest 2008-07-11 23:48:49.000000000 +0100 +++ cups-1.3.8/systemv/lp.c 2008-07-28 16:28:24.000000000 +0100 @@ -73,9 +73,7 @@ main(int argc, /* I - Number of comm int num_copies; /* Number of copies per file */ int num_files; /* Number of files to print */ const char *files[1000]; /* Files to print */ - int num_dests; /* Number of destinations */ - cups_dest_t *dests, /* Destinations */ - *dest; /* Selected destination */ + cups_dest_t *dest; /* Selected destination */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ int end_options; /* No more options? */ @@ -112,8 +110,7 @@ main(int argc, /* I - Number of comm silent = 0; printer = NULL; - num_dests = 0; - dests = NULL; + dest = NULL; num_options = 0; options = NULL; num_files = 0; @@ -179,10 +176,7 @@ main(int argc, /* I - Number of comm if ((instance = strrchr(printer, '/')) != NULL) *instance++ = '\0'; - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL) + if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL) { for (j = 0; j < dest->num_options; j ++) if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) @@ -593,10 +587,7 @@ main(int argc, /* I - Number of comm if (printer == NULL) { - if (num_dests == 0) - num_dests = cupsGetDests(&dests); - - if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) + if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) { printer = dest->name; @@ -625,7 +616,7 @@ main(int argc, /* I - Number of comm else val = "LPDEST"; - if (printer && !cupsGetDest(printer, NULL, num_dests, dests)) + if (printer && !cupsGetNamedDest(NULL, printer, NULL)) _cupsLangPrintf(stderr, _("%s: Error - %s environment variable names " "non-existent destination \"%s\"!\n"),