From 005dd1eb9e7844f4bf631111847c26c9a4b56df3 Mon Sep 17 00:00:00 2001 From: msweet Date: Thu, 24 Jul 2008 01:02:46 +0000 Subject: [PATCH] Merge changes from CUPS 1.4svn-r7791. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@886 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.3.txt | 9 +++ CHANGES.txt | 6 +- backend/usb-darwin.c | 71 +++++++++++------- backend/usb-libusb.c | 163 ++++++++++++++++++++++++++++++++++------ cups/Dependencies | 18 ++--- cups/conflicts.c | 52 +++++++------ cups/emit.c | 122 +++++++++++++++++++++++++++++- cups/libcups.exp | 1 + cups/page.c | 170 ++++++++++++++++++++++++++++++++++++++++++ cups/ppd.c | 24 ++++++ cups/ppd.h | 3 + cups/test2.ppd | 7 ++ cups/testppd.c | 118 +++++++++++++++++++++++++++++ doc/help/api-ppd.html | 28 +++++++ scheduler/ipp.c | 32 ++++++-- scheduler/job.c | 17 +++-- scheduler/log.c | 48 +++++++----- scheduler/printers.c | 3 +- systemv/cupstestppd.c | 8 +- tools/makesrcdist | 6 ++ 20 files changed, 786 insertions(+), 120 deletions(-) diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index 94106486d..fca0738fa 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -1,9 +1,18 @@ CHANGES-1.3.txt --------------- +CHANGES IN CUPS V1.3.9 + + - ppdEmit*() did not support custom JCL options (STR #2889) + - The cupstestppd utility incorrectly reported missing + "en" base translations (STR #2887) + + CHANGES IN CUPS V1.3.8 - Documentation updates (STR #2785, STR #2861, STR #2862) + - The scheduler did not add the ending job sheet when the + job was released. - The IPP backend did not relay marker-* attributes. - The CUPS GNOME/KDE menu item was not localized for Chinese (STR #2880) diff --git a/CHANGES.txt b/CHANGES.txt index 083ceae01..f3f407183 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,12 @@ -CHANGES.txt - 2008-07-18 +CHANGES.txt - 2008-07-23 ------------------------ CHANGES IN CUPS V1.4b1 + - Added ppdPageSizeLimits API. + - Added support for new cupsMediaQualifier2, cupsMediaQualifier3, + cupsMinSize, and cupsMaxSize attributes. + - Added cupsResolveConflicts and ppdInstallableConflict APIs. - Added support for new cupsUIConstraints and cupsUIResolver attributes for better option conflict detection and resolution. diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 28d45f29f..d0371378b 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -358,9 +358,14 @@ print_device(const char *uri, /* I - Device URI */ if (!g.make || !g.model) { - _cupsLangPrintf(stderr, - _("ERROR: Unable to create make and model strings\n")); - return CUPS_BACKEND_STOP; + _cupsLangPuts(stderr, _("ERROR: Fatal USB error!\n")); + + if (!g.make) + fputs("DEBUG: USB make string is NULL!\n", stderr); + if (!g.model) + fputs("DEBUG: USB model string is NULL!\n", stderr); + + return (CUPS_BACKEND_STOP); } fputs("STATE: +connecting-to-device\n", stderr); @@ -410,12 +415,13 @@ print_device(const char *uri, /* I - Device URI */ strlcpy(print_buffer, "USB class driver", sizeof(print_buffer)); fputs("STATE: +apple-missing-usbclassdriver-error\n", stderr); - _cupsLangPrintf(stderr, _("FATAL: Could not load %s\n"), print_buffer); + _cupsLangPuts(stderr, _("ERROR: Fatal USB error!\n")); + fprintf(stderr, "DEBUG: Could not load %s\n", print_buffer); if (driverBundlePath) CFRelease(driverBundlePath); - return CUPS_BACKEND_STOP; + return (CUPS_BACKEND_STOP); } if (driverBundlePath) @@ -427,8 +433,9 @@ print_device(const char *uri, /* I - Device URI */ countdown -= PRINTER_POLLING_INTERVAL; if (countdown <= 0) { - _cupsLangPrintf(stderr, _("INFO: Printer busy (status:0x%08x)\n"), - (int)status); + _cupsLangPuts(stderr, + _("INFO: Waiting for printer to become available...\n")); + fprintf(stderr, "DEBUG: USB printer status: 0x%08x\n", (int)status); countdown = SUBSEQUENT_LOG_INTERVAL; /* subsequent log entries, every 15 seconds */ } } @@ -473,8 +480,9 @@ print_device(const char *uri, /* I - Device URI */ if (pthread_create(&sidechannel_thread_id, NULL, sidechannel_thread, NULL)) { - _cupsLangPuts(stderr, _("WARNING: Couldn't create side channel\n")); - return CUPS_BACKEND_STOP; + _cupsLangPuts(stderr, _("ERROR: Fatal USB error!\n")); + fputs("DEBUG: Couldn't create side-channel thread!\n", stderr); + return (CUPS_BACKEND_STOP); } } @@ -490,8 +498,9 @@ print_device(const char *uri, /* I - Device URI */ if (pthread_create(&read_thread_id, NULL, read_thread, NULL)) { - _cupsLangPuts(stderr, _("WARNING: Couldn't create read channel\n")); - return CUPS_BACKEND_STOP; + _cupsLangPuts(stderr, _("ERROR: Fatal USB error!\n")); + fputs("DEBUG: Couldn't create read thread!\n", stderr); + return (CUPS_BACKEND_STOP); } /* @@ -505,7 +514,7 @@ print_device(const char *uri, /* I - Device URI */ while (status == noErr && copies-- > 0) { - _cupsLangPuts(stderr, _("INFO: Sending data\n")); + _cupsLangPuts(stderr, _("INFO: Sending print data...\n")); if (print_fd != STDIN_FILENO) { @@ -573,8 +582,9 @@ print_device(const char *uri, /* I - Device URI */ } else if (errno != EAGAIN) { - _cupsLangPrintf(stderr, _("ERROR: select() returned %d\n"), (int)errno); - return CUPS_BACKEND_STOP; + _cupsLangPuts(stderr, _("ERROR: Unable to read print data!\n")); + perror("DEBUG: select"); + return (CUPS_BACKEND_STOP); } } @@ -605,7 +615,8 @@ print_device(const char *uri, /* I - Device URI */ if (errno != EAGAIN || errno != EINTR) { - _cupsLangPrintError(_("ERROR: Unable to read print data")); + _cupsLangPuts(stderr, _("ERROR: Unable to read print data!\n")); + perror("DEBUG: read"); return CUPS_BACKEND_STOP; } @@ -649,8 +660,11 @@ print_device(const char *uri, /* I - Device URI */ */ OSStatus err = (*g.classdriver)->Abort(g.classdriver); - _cupsLangPrintf(stderr, _("ERROR: %ld: (canceled:%ld)\n"), - (long)status, (long)err); + _cupsLangPuts(stderr, _("ERROR: Unable to send print data!\n")); + fprintf(stderr, "DEBUG: USB class driver WritePipe returned %ld\n", + (long)status); + fprintf(stderr, "DEBUG: USB class driver Abort returned %ld\n", + (long)err); status = CUPS_BACKEND_STOP; break; } @@ -1705,7 +1719,7 @@ static void setup_cfLanguage(void) langArray = CFArrayCreate(kCFAllocatorDefault, (const void **)lang, sizeof(lang) / sizeof(lang[0]), &kCFTypeArrayCallBacks); CFPreferencesSetAppValue(CFSTR("AppleLanguages"), langArray, kCFPreferencesCurrentApplication); - fprintf(stderr, "DEBUG: usb: AppleLanguages = \"%s\"\n", requestedLang); + fprintf(stderr, "DEBUG: usb: AppleLanguages=\"%s\"\n", requestedLang); CFRelease(lang[0]); CFRelease(langArray); @@ -1801,7 +1815,8 @@ static void run_ppc_backend(int argc, execv("/usr/libexec/cups/backend/usb", my_argv); - _cupsLangPrintError(_("ERROR: Unable to exec /usr/libexec/cups/backend/usb")); + _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n")); + perror("DEBUG: Unable to exec /usr/libexec/cups/backend/usb"); exit(errno); } else if (child_pid < 0) @@ -1810,7 +1825,8 @@ static void run_ppc_backend(int argc, * Error - couldn't fork a new process! */ - _cupsLangPrintError(_("ERROR: Unable to fork")); + _cupsLangPrintf(stderr, _("Unable to use legacy USB class driver!\n")); + perror("DEBUG: Unable to fork"); exit(errno); } @@ -1827,7 +1843,8 @@ static void run_ppc_backend(int argc, close(fd); close(1); - fprintf(stderr, "DEBUG: Started usb(ppc) backend (PID %d)\n", (int)child_pid); + fprintf(stderr, "DEBUG: Started usb(legacy) backend (PID %d)\n", + (int)child_pid); while ((waitpid_status = waitpid(child_pid, &childstatus, 0)) == (pid_t)-1 && errno == EINTR) usleep(1000); @@ -1835,19 +1852,23 @@ static void run_ppc_backend(int argc, if (WIFSIGNALED(childstatus)) { exitstatus = WTERMSIG(childstatus); - fprintf(stderr, "DEBUG: usb(ppc) backend %d crashed on signal %d!\n", child_pid, exitstatus); + fprintf(stderr, "DEBUG: usb(legacy) backend %d crashed on signal %d!\n", + child_pid, exitstatus); } else { if ((exitstatus = WEXITSTATUS(childstatus)) != 0) - fprintf(stderr, "DEBUG: usb(ppc) backend %d stopped with status %d!\n", child_pid, exitstatus); + fprintf(stderr, + "DEBUG: usb(legacy) backend %d stopped with status %d!\n", + child_pid, exitstatus); else - fprintf(stderr, "DEBUG: PID %d exited with no errors\n", child_pid); + fprintf(stderr, "DEBUG: usb(legacy) backend %d exited with no errors\n", + child_pid); } } else { - fputs("DEBUG: usb child running i386 again\n", stderr); + fputs("DEBUG: usb(legacy) backend running native again\n", stderr); exitstatus = ENOENT; } diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c index a2ec1fa57..4a7716ec3 100644 --- a/backend/usb-libusb.c +++ b/backend/usb-libusb.c @@ -13,6 +13,16 @@ * * Contents: * + * list_devices() - List the available printers. + * print_device() - Print a file to a USB device. + * close_device() - Close the connection to the USB printer. + * find_device() - Find or enumerate USB printers. + * get_device_id() - Get the IEEE-1284 device ID for the printer. + * list_cb() - List USB printers for discovery. + * make_device_uri() - Create a device URI for a USB printer. + * open_device() - Open a connection to the USB printer. + * print_cb() - Find a USB printer for printing. + * side_cb() - Handle side-channel requests. */ /* @@ -20,6 +30,7 @@ */ #include +#include /* @@ -57,6 +68,7 @@ static char *make_device_uri(usb_printer_t *printer, static int open_device(usb_printer_t *printer, int verbose); static int print_cb(usb_printer_t *printer, const char *device_uri, const char *device_id, const void *data); +static ssize_t side_cb(usb_printer_t *printer, int print_fd); /* @@ -90,8 +102,7 @@ print_device(const char *uri, /* I - Device URI */ tbytes; /* Total bytes written */ char buffer[8192]; /* Print data buffer */ struct sigaction action; /* Actions for POSIX signals */ - int read_endp, /* Read endpoint */ - write_endp; /* Write endpoint */ + struct pollfd pfds[2]; /* Poll descriptors */ fputs("DEBUG: print_device\n", stderr); @@ -107,14 +118,6 @@ print_device(const char *uri, /* I - Device URI */ sleep(5); } - read_endp = printer->device->config[printer->conf]. - interface[printer->iface]. - altsetting[printer->altset]. - endpoint[printer->read_endp].bEndpointAddress; - write_endp = printer->device->config[printer->conf]. - interface[printer->iface]. - altsetting[printer->altset]. - endpoint[printer->write_endp].bEndpointAddress; /* * If we are printing data from a print driver on stdin, ignore SIGTERM @@ -134,6 +137,11 @@ print_device(const char *uri, /* I - Device URI */ tbytes = 0; + pfds[0].fd = print_fd; + pfds[0].events = POLLIN; + pfds[1].fd = CUPS_SC_FD; + pfds[1].events = POLLIN; + while (copies > 0 && tbytes >= 0) { copies --; @@ -145,23 +153,33 @@ print_device(const char *uri, /* I - Device URI */ } /* - * TODO: Add side-channel and back-channel support, along with better - * error handling for writes. + * TODO: Add back-channel support, along with better write error handling. */ - while ((bytes = read(print_fd, buffer, sizeof(buffer))) > 0) + if (poll(pfds, 2, -1) > 0) { - while (usb_bulk_write(printer->handle, write_endp, buffer, bytes, - 5000) < 0) + if (pfds[0].revents & POLLIN) { - _cupsLangPrintf(stderr, - _("ERROR: Unable to write %d bytes to printer!\n"), - (int)bytes); - tbytes = -1; - break; + if ((bytes = read(print_fd, buffer, sizeof(buffer))) > 0) + { + while (usb_bulk_write(printer->handle, printer->write_endp, buffer, + bytes, 5000) < 0) + { + _cupsLangPrintf(stderr, + _("ERROR: Unable to write %d bytes to printer!\n"), + (int)bytes); + tbytes = -1; + break; + } + + tbytes += bytes; + } + else if (bytes < 0 && errno != EAGAIN && errno != EINTR) + break; } - tbytes += bytes; + if (pfds[1].revents & POLLIN) + tbytes += side_cb(printer, print_fd); } } @@ -318,7 +336,19 @@ find_device(usb_cb_t cb, /* I - Callback function */ sizeof(device_uri)); if ((*cb)(&printer, device_uri, device_id, data)) + { + printer.read_endp = printer.device->config[printer.conf]. + interface[printer.iface]. + altsetting[printer.altset]. + endpoint[printer.read_endp]. + bEndpointAddress; + printer.write_endp = printer.device->config[printer.conf]. + interface[printer.iface]. + altsetting[printer.altset]. + endpoint[printer.write_endp]. + bEndpointAddress; return (&printer); + } } close_device(&printer); @@ -674,6 +704,97 @@ print_cb(usb_printer_t *printer, /* I - Printer */ } +/* + * 'side_cb()' - Handle side-channel requests. + */ + +static ssize_t /* O - Number of bytes written */ +side_cb(usb_printer_t *printer, /* I - Printer */ + int print_fd) /* I - File to print */ +{ + ssize_t bytes, /* Bytes read/written */ + tbytes; /* Total bytes written */ + char buffer[8192]; /* Print data buffer */ + struct pollfd pfd; /* Poll descriptor */ + cups_sc_command_t command; /* Request command */ + cups_sc_status_t status; /* Request/response status */ + char data[2048]; /* Request/response data */ + int datalen; /* Request/response data size */ + + + tbytes = 0; + datalen = sizeof(data); + + if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0)) + { + _cupsLangPuts(stderr, _("WARNING: Failed to read side-channel request!\n")); + return (0); + } + + switch (command) + { + case CUPS_SC_CMD_DRAIN_OUTPUT : + pfd.fd = print_fd; + pfd.events = POLLIN; + + while (poll(&pfd, 1, 1000) > 0) + { + if ((bytes = read(print_fd, buffer, sizeof(buffer))) > 0) + { + while (usb_bulk_write(printer->handle, printer->write_endp, buffer, + bytes, 5000) < 0) + { + _cupsLangPrintf(stderr, + _("ERROR: Unable to write %d bytes to printer!\n"), + (int)bytes); + tbytes = -1; + break; + } + + tbytes += bytes; + } + else if (bytes < 0 && errno != EAGAIN && errno != EINTR) + break; + } + + if (tbytes < 0) + status = CUPS_SC_STATUS_IO_ERROR; + else + status = CUPS_SC_STATUS_OK; + + datalen = 0; + break; + + case CUPS_SC_CMD_GET_BIDI : + data[0] = 0; /* TODO: Change to 1 when read supported */ + datalen = 1; + break; + + case CUPS_SC_CMD_GET_DEVICE_ID : + if (get_device_id(printer, data, sizeof(data))) + { + status = CUPS_SC_STATUS_IO_ERROR; + datalen = 0; + } + else + { + status = CUPS_SC_STATUS_OK; + datalen = strlen(data); + } + break; + + default : + status = CUPS_SC_STATUS_NOT_IMPLEMENTED; + datalen = 0; + break; + } + + cupsSideChannelWrite(command, status, data, datalen, 1.0); + + return (tbytes); +} + + /* * End of "$Id$". */ diff --git a/cups/Dependencies b/cups/Dependencies index 537343a45..7a32226fb 100644 --- a/cups/Dependencies +++ b/cups/Dependencies @@ -81,9 +81,9 @@ notify.o: i18n.h transcode.h options.o: cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h options.o: string.h ../config.h debug.h page.o: ppd.h array.h versioning.h file.h string.h ../config.h -ppd.o: globals.h string.h ../config.h http-private.h http.h versioning.h -ppd.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h -ppd.o: i18n.h transcode.h debug.h +ppd.o: ppd-private.h cups.h ipp.h http.h versioning.h ppd.h array.h file.h +ppd.o: language.h globals.h string.h ../config.h http-private.h md5.h +ppd.o: ipp-private.h i18n.h transcode.h debug.h request.o: globals.h string.h ../config.h http-private.h http.h versioning.h request.o: md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h request.o: i18n.h transcode.h debug.h @@ -207,9 +207,9 @@ notify.32.o: notify.c i18n.h transcode.h options.32.o: options.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h options.32.o: options.c string.h ../config.h debug.h page.32.o: page.c ppd.h array.h versioning.h file.h string.h ../config.h -ppd.32.o: ppd.c globals.h string.h ../config.h http-private.h http.h versioning.h -ppd.32.o: ppd.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h -ppd.32.o: ppd.c i18n.h transcode.h debug.h +ppd.32.o: ppd.c ppd-private.h cups.h ipp.h http.h versioning.h ppd.h array.h file.h +ppd.32.o: ppd.c language.h globals.h string.h ../config.h http-private.h md5.h +ppd.32.o: ppd.c ipp-private.h i18n.h transcode.h debug.h request.32.o: request.c globals.h string.h ../config.h http-private.h http.h versioning.h request.32.o: request.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h request.32.o: request.c i18n.h transcode.h debug.h @@ -333,9 +333,9 @@ notify.64.o: notify.c i18n.h transcode.h options.64.o: options.c cups.h ipp.h http.h versioning.h ppd.h array.h file.h language.h options.64.o: options.c string.h ../config.h debug.h page.64.o: page.c ppd.h array.h versioning.h file.h string.h ../config.h -ppd.64.o: ppd.c globals.h string.h ../config.h http-private.h http.h versioning.h -ppd.64.o: ppd.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h -ppd.64.o: ppd.c i18n.h transcode.h debug.h +ppd.64.o: ppd.c ppd-private.h cups.h ipp.h http.h versioning.h ppd.h array.h file.h +ppd.64.o: ppd.c language.h globals.h string.h ../config.h http-private.h md5.h +ppd.64.o: ppd.c ipp-private.h i18n.h transcode.h debug.h request.64.o: request.c globals.h string.h ../config.h http-private.h http.h versioning.h request.64.o: request.c md5.h ipp-private.h ipp.h cups.h ppd.h array.h file.h language.h request.64.o: request.c i18n.h transcode.h debug.h diff --git a/cups/conflicts.c b/cups/conflicts.c index 042bfdcec..f497f046f 100644 --- a/cups/conflicts.c +++ b/cups/conflicts.c @@ -234,7 +234,7 @@ cupsResolveConflicts( for (i = 0; i < *num_options; i ++) num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value, num_newopts, &newopts); - if (option) + if (option && strcasecmp(option, "Collate")) num_newopts = cupsAddOption(option, choice, num_newopts, &newopts); /* @@ -375,18 +375,28 @@ cupsResolveConflicts( } /* - * Free either the old or the new options depending on whether we had to - * apply any resolvers... + * Free the caller's option array... */ - if (resolvers) - { - cupsFreeOptions(*num_options, *options); - *num_options = num_newopts; - *options = newopts; - } + cupsFreeOptions(*num_options, *options); + + /* + * If Collate is the option we are testing, add it here. Otherwise, remove + * any Collate option from the resolve list since the filters automatically + * handle manual collation... + */ + + if (option && !strcasecmp(option, "Collate")) + num_newopts = cupsAddOption(option, choice, num_newopts, &newopts); else - cupsFreeOptions(num_newopts, newopts); + num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts); + + /* + * Return the new list of options to the caller... + */ + + *num_options = num_newopts; + *options = newopts; cupsArrayDelete(pass); cupsArrayDelete(resolvers); @@ -528,7 +538,7 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ for (i = 0, vptr = strchr(constattr->value, '*'); vptr; - i ++, vptr = strchr(vptr + 1, '*'), constptr ++) + i ++, vptr = strchr(vptr, '*'), constptr ++) { /* * Extract "*Option Choice" or just "*Option"... @@ -544,10 +554,7 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ vptr ++; if (*vptr == '*') - { - vptr --; choice[0] = '\0'; - } else { for (ptr = choice; *vptr && !isspace(*vptr & 255); vptr ++) @@ -568,9 +575,10 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ constptr->installable = ppd_is_installable(installable, option); consts->installable |= constptr->installable; - if (!constptr->option) + if (!constptr->option || (!constptr->choice && choice[0])) { - DEBUG_printf(("ppd_load_constraints: Unknown option %s!\n", option)); + DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n", + option, choice)); break; } } @@ -646,10 +654,10 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ oldconst->option1); } - if (!constptr[0].option) + if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0])) { - DEBUG_printf(("ppd_load_constraints: Unknown option %s!\n", - oldconst->option1)); + DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n", + oldconst->option1, oldconst->choice1)); free(consts->constraints); free(consts); continue; @@ -671,10 +679,10 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ oldconst->option2); } - if (!constptr->option) + if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0])) { - DEBUG_printf(("ppd_load_constraints: Unknown option %s!\n", - oldconst->option2)); + DEBUG_printf(("ppd_load_constraints: Unknown option *%s %s!\n", + oldconst->option2, oldconst->choice2)); free(consts->constraints); free(consts); continue; diff --git a/cups/emit.c b/cups/emit.c index 3e78be539..fed81fc48 100644 --- a/cups/emit.c +++ b/cups/emit.c @@ -618,7 +618,40 @@ ppdEmitString(ppd_file_t *ppd, /* I - PPD file record */ for (i = 0, bufsize = 1; i < count; i ++) { - if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + if (section == PPD_ORDER_JCL) + { + if (!strcasecmp(choices[i]->choice, "Custom") && + (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword)) + != NULL) + { + /* + * Add space to account for custom parameter substitution... + */ + + for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); + cparam; + cparam = (ppd_cparam_t *)cupsArrayNext(coption->params)) + { + switch (cparam->type) + { + case PPD_CUSTOM_CURVE : + case PPD_CUSTOM_INVCURVE : + case PPD_CUSTOM_POINTS : + case PPD_CUSTOM_REAL : + case PPD_CUSTOM_INT : + bufsize += 10; + break; + + case PPD_CUSTOM_PASSCODE : + case PPD_CUSTOM_PASSWORD : + case PPD_CUSTOM_STRING : + bufsize += strlen(cparam->current.custom_string); + break; + } + } + } + } + else if (section != PPD_ORDER_EXIT) { bufsize += 3; /* [{\n */ @@ -698,7 +731,89 @@ ppdEmitString(ppd_file_t *ppd, /* I - PPD file record */ */ for (i = 0, bufptr = buffer; i < count; i ++, bufptr += strlen(bufptr)) - if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL) + if (section == PPD_ORDER_JCL) + { + if (!strcasecmp(choices[i]->choice, "Custom") && + (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword)) + != NULL) + { + /* + * Handle substitutions in custom JCL options... + */ + + char *cptr; /* Pointer into code */ + int pnum; /* Parameter number */ + + + for (cptr = choices[i]->code; *cptr && bufptr < bufend;) + { + if (*cptr == '\\') + { + cptr ++; + + if (isdigit(*cptr & 255)) + { + /* + * Substitute parameter... + */ + + pnum = *cptr++ - '0'; + while (isalnum(*cptr & 255)) + pnum = pnum * 10 + *cptr - '0'; + + for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); + cparam; + cparam = (ppd_cparam_t *)cupsArrayNext(coption->params)) + if (cparam->order == pnum) + break; + + if (cparam) + { + switch (cparam->type) + { + case PPD_CUSTOM_CURVE : + case PPD_CUSTOM_INVCURVE : + case PPD_CUSTOM_POINTS : + case PPD_CUSTOM_REAL : + bufptr = _cupsStrFormatd(bufptr, bufend, + cparam->current.custom_real, + loc); + break; + + case PPD_CUSTOM_INT : + snprintf(bufptr, bufend - bufptr, "%d", + cparam->current.custom_int); + bufptr += strlen(bufptr); + break; + + case PPD_CUSTOM_PASSCODE : + case PPD_CUSTOM_PASSWORD : + case PPD_CUSTOM_STRING : + strlcpy(bufptr, cparam->current.custom_string, + bufend - bufptr); + bufptr += strlen(bufptr); + break; + } + } + } + else if (*cptr) + *bufptr++ = *cptr++; + } + else + *bufptr++ = *cptr++; + } + } + else + { + /* + * Otherwise just copy the option code directly... + */ + + strlcpy(bufptr, choices[i]->code, bufend - bufptr + 1); + bufptr += strlen(bufptr); + } + } + else if (section != PPD_ORDER_EXIT) { /* * Add wrapper commands to prevent printer errors for unsupported @@ -831,8 +946,7 @@ ppdEmitString(ppd_file_t *ppd, /* I - PPD file record */ } } else if (!strcasecmp(choices[i]->choice, "Custom") && - (coption = ppdFindCustomOption(ppd, - choices[i]->option->keyword)) + (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword)) != NULL) { /* diff --git a/cups/libcups.exp b/cups/libcups.exp index 53c15631a..8f34b3ccc 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -336,5 +336,6 @@ _ppdOpenFd _ppdOpenFile _ppdPageLength _ppdPageSize +_ppdPageSizeLimits _ppdPageWidth _ppdSetConformance diff --git a/cups/page.c b/cups/page.c index b4e325697..01a723e68 100644 --- a/cups/page.c +++ b/cups/page.c @@ -163,6 +163,176 @@ ppdPageSize(ppd_file_t *ppd, /* I - PPD file record */ } +/* + * 'ppdPageSizeLimits()' - Return the custom page size limits. + * + * This function returns the minimum and maximum custom page sizes and printable + * areas based on the currently-marked (selected) options. + * + * If the specified PPD file does not support custom page sizes, both + * "minimum" and "maximum" are filled with zeroes. + * + * @since CUPS 1.4@ + */ + +int /* O - 1 if custom sizes are supported, 0 otherwise */ +ppdPageSizeLimits(ppd_file_t *ppd, /* I - PPD file record */ + ppd_size_t *minimum, /* O - Minimum custom size */ + ppd_size_t *maximum) /* O - Maximum custom size */ +{ + ppd_choice_t *qualifier2, /* Second media qualifier */ + *qualifier3; /* Third media qualifier */ + ppd_attr_t *attr; /* Attribute */ + float width, /* Min/max width */ + length; /* Min/max length */ + char spec[PPD_MAX_NAME]; /* Selector for min/max */ + + + /* + * Range check input... + */ + + if (!ppd || !ppd->variable_sizes || !minimum || !maximum) + { + if (minimum) + memset(minimum, 0, sizeof(ppd_size_t)); + + if (maximum) + memset(maximum, 0, sizeof(ppd_size_t)); + + return (0); + } + + /* + * See if we have the cupsMediaQualifier2 and cupsMediaQualifier3 attributes... + */ + + cupsArraySave(ppd->sorted_attrs); + + if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier2", NULL)) != NULL && + attr->value) + qualifier2 = ppdFindMarkedChoice(ppd, attr->value); + else + qualifier2 = NULL; + + if ((attr = ppdFindAttr(ppd, "cupsMediaQualifier3", NULL)) != NULL && + attr->value) + qualifier3 = ppdFindMarkedChoice(ppd, attr->value); + else + qualifier3 = NULL; + + /* + * Figure out the current minimum width and length... + */ + + if (qualifier2) + { + /* + * Try getting cupsMinSize... + */ + + if (qualifier3) + { + snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice, + qualifier3->choice); + attr = ppdFindAttr(ppd, "cupsMinSize", spec); + } + else + attr = NULL; + + if (!attr) + { + snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice); + attr = ppdFindAttr(ppd, "cupsMinSize", spec); + } + + if (!attr && qualifier3) + { + snprintf(spec, sizeof(spec), "..%s", qualifier3->choice); + attr = ppdFindAttr(ppd, "cupsMinSize", spec); + } + + if (!attr || + (attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2)) + { + width = ppd->custom_min[0]; + length = ppd->custom_min[1]; + } + } + else + { + width = ppd->custom_min[0]; + length = ppd->custom_min[1]; + } + + minimum->width = width; + minimum->length = length; + minimum->left = ppd->custom_margins[0]; + minimum->bottom = ppd->custom_margins[1]; + minimum->right = width - ppd->custom_margins[2]; + minimum->top = length - ppd->custom_margins[3]; + + /* + * Figure out the current maximum width and length... + */ + + if (qualifier2) + { + /* + * Try getting cupsMaxSize... + */ + + if (qualifier3) + { + snprintf(spec, sizeof(spec), ".%s.%s", qualifier2->choice, + qualifier3->choice); + attr = ppdFindAttr(ppd, "cupsMaxSize", spec); + } + else + attr = NULL; + + if (!attr) + { + snprintf(spec, sizeof(spec), ".%s.", qualifier2->choice); + attr = ppdFindAttr(ppd, "cupsMaxSize", spec); + } + + if (!attr && qualifier3) + { + snprintf(spec, sizeof(spec), "..%s", qualifier3->choice); + attr = ppdFindAttr(ppd, "cupsMaxSize", spec); + } + + if (!attr || + (attr->value && sscanf(attr->value, "%f%f", &width, &length) != 2)) + { + width = ppd->custom_max[0]; + length = ppd->custom_max[1]; + } + } + else + { + width = ppd->custom_max[0]; + length = ppd->custom_max[1]; + } + + maximum->width = width; + maximum->length = length; + maximum->left = ppd->custom_margins[0]; + maximum->bottom = ppd->custom_margins[1]; + maximum->right = width - ppd->custom_margins[2]; + maximum->top = length - ppd->custom_margins[3]; + + /* + * Return the min and max... + */ + + cupsArrayRestore(ppd->sorted_attrs); + + return (1); +} + + /* * 'ppdPageWidth()' - Get the page width for the given size. */ diff --git a/cups/ppd.c b/cups/ppd.c index 436dd05f2..75db5c5ac 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -59,6 +59,7 @@ * Include necessary headers. */ +#include "ppd-private.h" #include "globals.h" #include "debug.h" #include @@ -291,6 +292,26 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ cupsArrayDelete(ppd->coptions); + /* + * Free constraints... + */ + + if (ppd->cups_uiconstraints) + { + _ppd_cups_uiconsts_t *consts; /* Current constraints */ + + + for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints); + consts; + consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints)) + { + free(consts->constraints); + free(consts); + } + + cupsArrayDelete(ppd->cups_uiconstraints); + } + /* * Free the whole record... */ @@ -1042,6 +1063,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ sizeof(choice->text)); choice->code = _cupsStrAlloc(string); + + if (custom_option->section == PPD_ORDER_JCL) + ppd_decode(choice->code); } /* diff --git a/cups/ppd.h b/cups/ppd.h index 4261aae1a..325c36245 100644 --- a/cups/ppd.h +++ b/cups/ppd.h @@ -409,6 +409,9 @@ extern ppd_attr_t *ppdLocalizeAttr(ppd_file_t *ppd, const char *keyword, const char *spec); extern const char *ppdLocalizeMarkerName(ppd_file_t *ppd, const char *name) _CUPS_API_1_4; +extern int ppdPageSizeLimits(ppd_file_t *ppd, + ppd_size_t *minimum, + ppd_size_t *maximum) _CUPS_API_1_4; /* diff --git a/cups/test2.ppd b/cups/test2.ppd index 9cd9d22e5..a553ba4b7 100644 --- a/cups/test2.ppd +++ b/cups/test2.ppd @@ -116,6 +116,13 @@ *ParamCustomPageSize HeightOffset/Height Offset: 4 points 0 0 *ParamCustomPageSize Orientation: 5 int 0 0 +*cupsMediaQualifier2: InputSlot +*cupsMediaQualifier3: Quality +*cupsMaxSize .Manual.: "1000 1000" +*cupsMinSize .Manual.: "100 100" +*cupsMinSize .Manual.Photo: "200 200" +*cupsMinSize ..Photo: "300 300" + *OpenUI *InputSlot/Input Slot: PickOne *OrderDependency: 20 AnySetup *InputSlot *DefaultInputSlot: Tray diff --git a/cups/testppd.c b/cups/testppd.c index 10f11650f..943e390e1 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -112,6 +112,8 @@ main(int argc, /* I - Number of command-line arguments */ const char *text; /* Localized text */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ + ppd_size_t minsize, /* Minimum size */ + maxsize; /* Maximum size */ status = 0; @@ -254,6 +256,30 @@ main(int argc, /* I - Number of command-line arguments */ status ++; } + /* + * ppdPageSizeLimits + */ + + fputs("ppdPageSizeLimits: ", stdout); + if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) + { + if (minsize.width != 36 || minsize.length != 36 || + maxsize.width != 1080 || maxsize.length != 86400) + { + printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " + "expected min=36x36, max=1080x86400)\n", minsize.width, + minsize.length, maxsize.width, maxsize.length); + status ++; + } + else + puts("PASS"); + } + else + { + puts("FAIL (returned 0)"); + status ++; + } + /* * Test localization... */ @@ -477,6 +503,98 @@ main(int argc, /* I - Number of command-line arguments */ puts("FAIL (Duplex=None conflicted)"); status ++; } + + /* + * ppdPageSizeLimits + */ + + ppdMarkDefaults(ppd); + + fputs("ppdPageSizeLimits(default): ", stdout); + if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) + { + if (minsize.width != 36 || minsize.length != 36 || + maxsize.width != 1080 || maxsize.length != 86400) + { + printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " + "expected min=36x36, max=1080x86400)\n", minsize.width, + minsize.length, maxsize.width, maxsize.length); + status ++; + } + else + puts("PASS"); + } + else + { + puts("FAIL (returned 0)"); + status ++; + } + + ppdMarkOption(ppd, "InputSlot", "Manual"); + + fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout); + if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) + { + if (minsize.width != 100 || minsize.length != 100 || + maxsize.width != 1000 || maxsize.length != 1000) + { + printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " + "expected min=100x100, max=1000x1000)\n", minsize.width, + minsize.length, maxsize.width, maxsize.length); + status ++; + } + else + puts("PASS"); + } + else + { + puts("FAIL (returned 0)"); + status ++; + } + + ppdMarkOption(ppd, "Quality", "Photo"); + + fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); + if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) + { + if (minsize.width != 200 || minsize.length != 200 || + maxsize.width != 1000 || maxsize.length != 1000) + { + printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " + "expected min=200x200, max=1000x1000)\n", minsize.width, + minsize.length, maxsize.width, maxsize.length); + status ++; + } + else + puts("PASS"); + } + else + { + puts("FAIL (returned 0)"); + status ++; + } + + ppdMarkOption(ppd, "InputSlot", "Tray"); + + fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); + if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) + { + if (minsize.width != 300 || minsize.length != 300 || + maxsize.width != 1080 || maxsize.length != 86400) + { + printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " + "expected min=300x300, max=1080x86400)\n", minsize.width, + minsize.length, maxsize.width, maxsize.length); + status ++; + } + else + puts("PASS"); + } + else + { + puts("FAIL (returned 0)"); + status ++; + } } else { diff --git a/doc/help/api-ppd.html b/doc/help/api-ppd.html index 125c7b29b..2bb61a07d 100644 --- a/doc/help/api-ppd.html +++ b/doc/help/api-ppd.html @@ -345,6 +345,7 @@ conflicts.">ppdMarkOption
  • ppdOpenFile
  • ppdPageLength
  • ppdPageSize
  • +
  • ppdPageSizeLimits
  • ppdPageWidth
  • ppdSetConformance
  • @@ -1368,6 +1369,33 @@ float ppdPageLength (

    Return Value

    Size record for page or NULL

    +

     CUPS 1.4 ppdPageSizeLimits

    +

    Return the custom page size limits.

    +

    +int ppdPageSizeLimits (
    +    ppd_file_t *ppd,
    +    ppd_size_t *minimum,
    +    ppd_size_t *maximum
    +);

    +

    Parameters

    +
    +
    ppd
    +
    PPD file record
    +
    minimum
    +
    Minimum custom size
    +
    maximum
    +
    Maximum custom size
    +
    +

    Return Value

    +

    1 if custom sizes are supported, 0 otherwise

    +

    Discussion

    +

    This function returns the minimum and maximum custom page sizes and printable +areas based on the currently-marked (selected) options.
    +
    +If the specified PPD file does not support custom page sizes, both +"minimum" and "maximum" are filled with zeroes. + +

    ppdPageWidth

    Get the page width for the given size.

    diff --git a/scheduler/ipp.c b/scheduler/ipp.c index cd8b6c26e..b8fbeaa5c 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -8928,6 +8928,8 @@ release_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogJob(job, CUPSD_LOG_INFO, "Released by \"%s\".", username); con->response->request.status.status_code = IPP_OK; + + cupsdCheckJobs(); } @@ -9971,6 +9973,7 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ /* Resource portion of URI */ int port; /* Port portion of URI */ int event; /* Events? */ + int check_jobs; /* Check jobs? */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con, @@ -10072,7 +10075,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ cupsdLoadJob(job); - event = 0; + check_jobs = 0; + event = 0; for (attr = con->request->attrs; attr; attr = attr->next) { @@ -10138,9 +10142,13 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ } else if (con->response->request.status.status_code == IPP_OK) { + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-priority to %d", + attr->values[0].integer); cupsdSetJobPriority(job, attr->values[0].integer); - event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | - CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED; + + check_jobs = 1; + event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | + CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED; } } else if (!strcmp(attr->name, "job-state")) @@ -10170,10 +10178,14 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ } else if (con->response->request.status.status_code == IPP_OK) { + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d", + attr->values[0].integer); + job->state->values[0].integer = attr->values[0].integer; job->state_value = (ipp_jstate_t)attr->values[0].integer; event |= CUPSD_EVENT_JOB_STATE; + check_jobs = 1; } break; @@ -10197,7 +10209,13 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ return; } else if (con->response->request.status.status_code == IPP_OK) + { + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d", + attr->values[0].integer); cupsdCancelJob(job, 0, (ipp_jstate_t)attr->values[0].integer); + + check_jobs = 1; + } break; } } @@ -10233,6 +10251,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (!strcmp(attr->name, "job-hold-until")) { + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-hold-until to %s", + attr->values[0].string.text); cupsdSetJobHoldUntil(job, attr->values[0].string.text); if (!strcmp(attr->values[0].string.text, "no-hold")) @@ -10240,7 +10260,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ else cupsdHoldJob(job); - event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE; + check_jobs = 1; + event |= CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_STATE; } } else if (attr->value_tag == IPP_TAG_DELETEATTR) @@ -10306,7 +10327,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ * Start jobs if possible... */ - cupsdCheckJobs(); + if (check_jobs) + cupsdCheckJobs(); } diff --git a/scheduler/job.c b/scheduler/job.c index 0669ec028..e0bd77534 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -373,8 +373,9 @@ cupsdCheckJobs(void) */ cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdCheckJobs: Job %d: state_value=%d, loaded=%s", - job->id, job->state_value, job->attrs ? "yes" : "no"); + "cupsdCheckJobs: Job %d: dest=%s, dtype=%x, " + "state_value=%d, loaded=%s", job->id, job->dest, job->dtype, + job->state_value, job->attrs ? "yes" : "no"); if (job->state_value == IPP_JOB_HELD && job->hold_until && @@ -955,8 +956,6 @@ cupsdHoldJob(cupsd_job_t *job) /* I - Job data */ job->dirty = 1; cupsdMarkDirty(CUPSD_DIRTY_JOBS); - - cupsdCheckJobs(); } @@ -1380,13 +1379,19 @@ cupsdReleaseJob(cupsd_job_t *job) /* I - Job */ if (job->state_value == IPP_JOB_HELD) { + /* + * Add trailing banner as needed... + */ + + if (job->pending_timeout) + cupsdTimeoutJob(job); + DEBUG_puts("cupsdReleaseJob: setting state to pending..."); job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; job->dirty = 1; cupsdMarkDirty(CUPSD_DIRTY_JOBS); - cupsdCheckJobs(); } } @@ -1418,8 +1423,6 @@ cupsdRestartJob(cupsd_job_t *job) /* I - Job */ if (old_state > IPP_JOB_STOPPED) cupsArrayAdd(ActiveJobs, job); - - cupsdCheckJobs(); } } diff --git a/scheduler/log.c b/scheduler/log.c index 1eb10c2d0..dc2e23297 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -47,7 +47,7 @@ static char *log_line = NULL; /* Line for output file */ */ static int check_log_file(cups_file_t **lf, const char *logname); -static char *format_log_line(const char *message, va_list ap); +static int format_log_line(const char *message, va_list ap); /* @@ -175,8 +175,8 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ ...) /* I - Additional arguments as needed */ { va_list ap; /* Argument pointer */ - char jobmsg[1024], /* Format string for job message */ - *line; /* Message line */ + char jobmsg[1024]; /* Format string for job message */ + int status; /* Formatting status */ /* @@ -192,12 +192,16 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ snprintf(jobmsg, sizeof(jobmsg), "[Job %d] %s", job->id, message); - va_start(ap, message); - line = format_log_line(jobmsg, ap); - va_end(ap); + do + { + va_start(ap, message); + status = format_log_line(jobmsg, ap); + va_end(ap); + } + while (status == 0); - if (line) - return (cupsdWriteErrorLog(level, line)); + if (status > 0) + return (cupsdWriteErrorLog(level, log_line)); else return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, "Unable to allocate memory for log line!")); @@ -214,7 +218,7 @@ cupsdLogMessage(int level, /* I - Log level */ ...) /* I - Additional args as needed */ { va_list ap; /* Argument pointer */ - char *line; /* Message line */ + int status; /* Formatting status */ /* @@ -241,12 +245,16 @@ cupsdLogMessage(int level, /* I - Log level */ * Format and write the log message... */ - va_start(ap, message); - line = format_log_line(message, ap); - va_end(ap); + do + { + va_start(ap, message); + status = format_log_line(message, ap); + va_end(ap); + } + while (status == 0); - if (line) - return (cupsdWriteErrorLog(level, line)); + if (status > 0) + return (cupsdWriteErrorLog(level, log_line)); else return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, "Unable to allocate memory for log line!")); @@ -870,11 +878,11 @@ check_log_file(cups_file_t **lf, /* IO - Log file */ * to format_log_line()... */ -static char * /* O - Text or NULL on error */ +static int /* O - -1 for fatal, 0 for retry, 1 for success */ format_log_line(const char *message, /* I - Printf-style format string */ va_list ap) /* I - Argument list */ { - int len; /* Length of formatted line */ + int len; /* Length of formatted line */ /* @@ -887,7 +895,7 @@ format_log_line(const char *message, /* I - Printf-style format string */ log_line = malloc(log_linesize); if (!log_line) - return (NULL); + return (-1); } /* @@ -918,12 +926,12 @@ format_log_line(const char *message, /* I - Printf-style format string */ { log_line = temp; log_linesize = len; - } - vsnprintf(log_line, log_linesize, message, ap); + return (0); + } } - return (log_line); + return (1); } diff --git a/scheduler/printers.c b/scheduler/printers.c index c675e090d..df8f7f24c 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -2402,7 +2402,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if ((duplex = ppdFindOption(ppd, "KD03Duplex")) == NULL) duplex = ppdFindOption(ppd, "JCLDuplex"); - if (duplex && duplex->num_choices > 1) + if (duplex && duplex->num_choices > 1 && + !ppdInstallableConflict(ppd, duplex->keyword, "DuplexTumble")) { p->type |= CUPS_PRINTER_DUPLEX; diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c index f376dd46e..b8052b3b5 100644 --- a/systemv/cupstestppd.c +++ b/systemv/cupstestppd.c @@ -1767,7 +1767,7 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */ for (vptr = strchr(constattr->value, '*'); vptr; - vptr = strchr(vptr + 1, '*')) + vptr = strchr(vptr, '*')) { /* * Extract "*Option Choice" or just "*Option"... @@ -1783,10 +1783,7 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */ vptr ++; if (*vptr == '*') - { - vptr --; choice[0] = '\0'; - } else { for (ptr = choice; *vptr && !isspace(*vptr & 255); vptr ++) @@ -2533,7 +2530,8 @@ check_translations(ppd_file_t *ppd, /* I - PPD file */ strlcpy(ll, language, sizeof(ll)); - if (!cupsArrayFind(languages, ll) && strcmp(ll, "zh")) + if (!cupsArrayFind(languages, ll) && + strcmp(ll, "zh") && strcmp(ll, "en")) { if (!warn && !errors && !verbose) _cupsLangPuts(stdout, _(" FAIL\n")); diff --git a/tools/makesrcdist b/tools/makesrcdist index 53ede17d5..c25dfc49d 100755 --- a/tools/makesrcdist +++ b/tools/makesrcdist @@ -75,6 +75,12 @@ sed -e '1,$s/@CUPS_VERSION@/'$version'/' \ tar cjf cups-$fileversion-source.tar.bz2 cups-$version echo "..." +if test -x /usr/bin/md5sum; then + (cd /tmp; md5sum cups-$fileversion-source.tar.* | awk '{print $1, "'$fileversion' cups/'$fileversion'/" $2}') +elif test -x /sbin/md5; then + (cd /tmp; md5 cups-$fileversion-source.tar.* | awk '{print $4, "'$fileversion' cups/'$fileversion'/" substr($2, 2, length($2) - 2)}') +fi + echo Removing temporary files... rm -rf cups-$version -- 2.39.2