diff options
Diffstat (limited to 'filter/commandtops.c')
-rw-r--r-- | filter/commandtops.c | 211 |
1 files changed, 189 insertions, 22 deletions
diff --git a/filter/commandtops.c b/filter/commandtops.c index ce3ea99c..745359ec 100644 --- a/filter/commandtops.c +++ b/filter/commandtops.c @@ -1,9 +1,9 @@ /* - * "$Id: commandtops.c 9793 2011-05-20 03:49:49Z mike $" + * "$Id: commandtops.c 10373 2012-03-21 23:00:05Z mike $" * * PostScript command filter for CUPS. * - * Copyright 2008-2011 by Apple Inc. + * Copyright 2008-2012 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -36,7 +36,7 @@ * Local functions... */ -static void auto_configure(ppd_file_t *ppd, const char *user); +static int auto_configure(ppd_file_t *ppd, const char *user); static void begin_ps(ppd_file_t *ppd, const char *user); static void end_ps(ppd_file_t *ppd); static void print_self_test_page(ppd_file_t *ppd, const char *user); @@ -51,6 +51,7 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { + int status = 0; /* Exit status */ cups_file_t *fp; /* Command file */ char line[1024], /* Line from file */ *value; /* Value on line */ @@ -113,16 +114,20 @@ main(int argc, /* I - Number of command-line arguments */ */ if (!_cups_strcasecmp(line, "AutoConfigure")) - auto_configure(ppd, argv[2]); + status |= auto_configure(ppd, argv[2]); else if (!_cups_strcasecmp(line, "PrintSelfTestPage")) print_self_test_page(ppd, argv[2]); else if (!_cups_strcasecmp(line, "ReportLevels")) report_levels(ppd, argv[2]); else - fprintf(stderr, "ERROR: Invalid printer command \"%s\"!\n", line); + { + _cupsLangPrintFilter(stderr, "ERROR", + _("Invalid printer command \"%s\"."), line); + status = 1; + } } - return (0); + return (status); } @@ -131,12 +136,14 @@ main(int argc, /* I - Number of command-line arguments */ * query commands and/or SNMP lookups. */ -static void +static int /* O - Exit status */ auto_configure(ppd_file_t *ppd, /* I - PPD file */ const char *user) /* I - Printing user */ { + int status = 0; /* Exit status */ ppd_option_t *option; /* Current option in PPD */ ppd_attr_t *attr; /* Query command attribute */ + const char *valptr; /* Pointer into attribute value */ char buffer[1024], /* String buffer */ *bufptr; /* Pointer into buffer */ ssize_t bytes; /* Number of bytes read */ @@ -154,7 +161,7 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ { fputs("DEBUG: Unable to auto-configure PostScript Printer - no " "bidirectional I/O available!\n", stderr); - return; + return (1); } /* @@ -162,6 +169,25 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ */ begin_ps(ppd, user); + + /* + * (STR #4028) + * + * As a lot of PPDs contain bad PostScript query code, we need to prevent one + * bad query sequence from affecting all auto-configuration. The following + * error handler allows us to log PostScript errors to cupsd. + */ + + puts("/cups_handleerror {\n" + " $error /newerror false put\n" + " (:PostScript error in \") print cups_query_keyword print (\": ) " + "print\n" + " $error /errorname get 128 string cvs print\n" + " (; offending command:) print $error /command get 128 string cvs " + "print (\n) print flush\n" + "} bind def\n" + "errordict /timeout {} put\n" + "/cups_query_keyword (?Unknown) def\n"); fflush(stdout); /* @@ -202,7 +228,76 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ */ fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword); - fputs(attr->value, stdout); + + for (bufptr = buffer, valptr = attr->value; *valptr; valptr ++) + { + /* + * Log the query code, breaking at newlines... + */ + + if (*valptr == '\n') + { + *bufptr = '\0'; + fprintf(stderr, "DEBUG: %s\\n\n", buffer); + bufptr = buffer; + } + else if (*valptr < ' ') + { + if (bufptr >= (buffer + sizeof(buffer) - 4)) + { + *bufptr = '\0'; + fprintf(stderr, "DEBUG: %s\n", buffer); + bufptr = buffer; + } + + if (*valptr == '\r') + { + *bufptr++ = '\\'; + *bufptr++ = 'r'; + } + else if (*valptr == '\t') + { + *bufptr++ = '\\'; + *bufptr++ = 't'; + } + else + { + *bufptr++ = '\\'; + *bufptr++ = '0' + ((*valptr / 64) & 7); + *bufptr++ = '0' + ((*valptr / 8) & 7); + *bufptr++ = '0' + (*valptr & 7); + } + } + else + { + if (bufptr >= (buffer + sizeof(buffer) - 1)) + { + *bufptr = '\0'; + fprintf(stderr, "DEBUG: %s\n", buffer); + bufptr = buffer; + } + + *bufptr++ = *valptr; + } + } + + if (bufptr > buffer) + { + *bufptr = '\0'; + fprintf(stderr, "DEBUG: %s\n", buffer); + } + + printf("/cups_query_keyword (?%s) def\n", option->keyword); + /* Set keyword for error reporting */ + fputs("{ (", stdout); + for (valptr = attr->value; *valptr; valptr ++) + { + if (*valptr == '(' || *valptr == ')' || *valptr == '\\') + putchar('\\'); + putchar(*valptr); + } + fputs(") cvx exec } stopped { cups_handleerror } if clear\n", stdout); + /* Send query code */ fflush(stdout); datalen = 0; @@ -212,53 +307,119 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ * Read the response data... */ - while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 90.0)) > 0) + bufptr = buffer; + buffer[0] = '\0'; + while ((bytes = cupsBackChannelRead(bufptr, + sizeof(buffer) - (bufptr - buffer) - 1, + 10.0)) > 0) { /* - * Trim whitespace from both ends... + * No newline at the end? Go on reading ... */ - buffer[bytes] = '\0'; + bufptr += bytes; + *bufptr = '\0'; + + if (bytes == 0 || + (bufptr > buffer && bufptr[-1] != '\r' && bufptr[-1] != '\n')) + continue; - for (bufptr = buffer + bytes - 1; bufptr >= buffer; bufptr --) - if (isspace(*bufptr & 255)) + /* + * Trim whitespace and control characters from both ends... + */ + + bytes = bufptr - buffer; + + for (bufptr --; bufptr >= buffer; bufptr --) + if (isspace(*bufptr & 255) || iscntrl(*bufptr & 255)) *bufptr = '\0'; else break; - for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++); + for (bufptr = buffer; isspace(*bufptr & 255) || iscntrl(*bufptr & 255); + bufptr ++); + + if (bufptr > buffer) + { + _cups_strcpy(buffer, bufptr); + bufptr = buffer; + } - fprintf(stderr, "DEBUG: Got \"%s\" (%d bytes)\n", bufptr, (int)bytes); + fprintf(stderr, "DEBUG: Got %d bytes.\n", (int)bytes); /* * Skip blank lines... */ - if (!*bufptr) + if (!buffer[0]) continue; /* + * Check the response... + */ + + if ((bufptr = strchr(buffer, ':')) != NULL) + { + /* + * PostScript code for this option in the PPD is broken; show the + * interpreter's error message that came back... + */ + + fprintf(stderr, "DEBUG%s\n", bufptr); + break; + } + + /* * Verify the result is a valid option choice... */ - if (!ppdFindChoice(option, bufptr)) + if (!ppdFindChoice(option, buffer)) + { + if (!strcasecmp(buffer, "Unknown")) + break; + + bufptr = buffer; + buffer[0] = '\0'; continue; + } /* * Write out the result and move on to the next option... */ - fprintf(stderr, "DEBUG: Default%s=%s\n", option->keyword, bufptr); - fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, bufptr); + fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, buffer); break; } + + /* + * Printer did not answer this option's query + */ + + if (bytes <= 0) + { + fprintf(stderr, + "DEBUG: No answer to query for option %s within 10 seconds.\n", + option->keyword); + status = 1; + } } /* * Finish the job... */ + fflush(stdout); end_ps(ppd); + + /* + * Return... + */ + + if (status) + _cupsLangPrintFilter(stderr, "WARNING", + _("Unable to configure printer options.")); + + return (0); } @@ -280,6 +441,7 @@ begin_ps(ppd_file_t *ppd, /* I - PPD file */ puts("%!"); puts("userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n"); + fflush(stdout); } @@ -319,7 +481,12 @@ print_self_test_page(ppd_file_t *ppd, /* I - PPD file */ * the product/interpreter information... */ - puts("% You are using the wrong driver for your printer!\n" + puts("\r%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" + "%%%%%%%%%%%%%\n" + "\r%%%% If you can read this, you are using the wrong driver for your " + "printer. %%%%\n" + "\r%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" + "%%%%%%%%%%%%%\n" "0 setgray\n" "2 setlinewidth\n" "initclip newpath clippath gsave stroke grestore pathbbox\n" @@ -367,5 +534,5 @@ report_levels(ppd_file_t *ppd, /* I - PPD file */ /* - * End of "$Id: commandtops.c 9793 2011-05-20 03:49:49Z mike $". + * End of "$Id: commandtops.c 10373 2012-03-21 23:00:05Z mike $". */ |