From ae71f5deb42f3d526b5f35d2eed9241abb6405ba Mon Sep 17 00:00:00 2001 From: msweet Date: Thu, 17 Apr 2008 00:50:22 +0000 Subject: [PATCH] Import CUPS 1.4svn-r7464. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@713 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.3.txt | 10 +- CHANGES.txt | 7 +- backend/Makefile | 4 +- backend/snmp.c | 13 +- backend/test1284.c | 4 +- backend/usb-darwin.c | 2 +- berkeley/lpq.c | 6 +- cgi-bin/help-index.c | 4 +- cgi-bin/var.c | 29 +- conf/cupsd.conf.in | 2 +- config-scripts/cups-compiler.m4 | 1 + config-scripts/cups-defaults.m4 | 4 +- config-scripts/cups-pdf.m4 | 15 +- config.h.in | 11 +- cups/Makefile | 18 +- cups/array.c | 5 +- cups/auth.c | 2 +- cups/cups.h | 14 +- cups/debug.c | 452 +++++++++++++++++++ cups/debug.h | 25 +- cups/dest.c | 2 +- cups/emit.c | 5 +- cups/encode.c | 6 +- cups/file.h | 6 +- cups/getdevices.c | 259 +++++++++++ cups/globals.c | 14 +- cups/globals.h | 6 + cups/http-addrlist.c | 13 +- cups/http.c | 143 +++--- cups/ipp-support.c | 2 +- cups/ipp.c | 26 +- cups/language.c | 3 +- cups/libcups.exp | 3 + cups/localize.c | 6 +- cups/mark.c | 4 +- cups/ppd.c | 29 +- cups/request.c | 4 +- cups/string.c | 4 +- cups/testfile.c | 43 +- cups/util.c | 2 +- doc/help/api-cups.html | 106 +---- doc/help/api-httpipp.html | 133 +++++- doc/help/spec-ipp.html | 11 + filter/error.c | 9 +- filter/interpret.c | 74 ++-- filter/pdftops.c | 67 ++- filter/rastertoepson.c | 5 - filter/rastertolabel.c | 3 - notifier/mailto.c | 4 +- notifier/rss.c | 7 +- ppdc/ppdc-catalog.cxx | 6 +- scheduler/client.c | 5 +- scheduler/conf.c | 8 +- scheduler/cups-deviced.c | 754 ++++++++++++++++++++------------ scheduler/filter.c | 14 +- scheduler/ipp.c | 28 +- scheduler/main.c | 6 +- systemv/lpinfo.c | 154 ++----- 58 files changed, 1821 insertions(+), 781 deletions(-) create mode 100644 cups/debug.c create mode 100644 cups/getdevices.c diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index e2b84293e..271225ac7 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -4,10 +4,16 @@ CHANGES-1.3.txt CHANGES IN CUPS V1.3.8 - Documentation updates (STR #2785) - - The scheduler did not reject requests with an empty - Content-Length field (STR #2787) + - The scheduler now ensures that the RSS directory has + the correct permissions. + - The RSS notifier did not quote the feed URL in the RSS + file it created (STR #2801) - The web interface allowed the creation and cancellation of RSS subscriptions without a username (STR #2774) + - Increased the default MaxCopies value on Mac OS X to + 9999 to match the limit imposed by the print dialog. + - The scheduler did not reject requests with an empty + Content-Length field (STR #2787) - The PNG image loading code would crash with large images (STR #2790) - The scheduler did not log the current date and time and diff --git a/CHANGES.txt b/CHANGES.txt index 7c0a2f2b2..de23174da 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,13 @@ -CHANGES.txt - 2008-04-08 +CHANGES.txt - 2008-04-14 ------------------------ CHANGES IN CUPS V1.4b1 + - The CUPS-Get-Devices operation now supports the + exclude-schemes and timeout attributes to control which + backends are polled and for how long. + - The cups-deviced helper application now runs backends in + parallel to get the list of devices faster. - Added --enable-pap configure option. - The default cupsd.conf file now includes an "authenticated" policy which requires authentication for remote print jobs. diff --git a/backend/Makefile b/backend/Makefile index c898b3db0..c8af61b38 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -119,7 +119,7 @@ uninstall: test1284: test1284.o ../cups/libcups.a echo Linking $@... $(CC) $(LDFLAGS) -o test1284 test1284.o ../cups/libcups.a \ - $(SSLLIBS) $(COMMONLIBS) $(LIBZ) + $(LIBGSSAPI) $(SSLLIBS) $(COMMONLIBS) $(LIBZ) # @@ -129,7 +129,7 @@ test1284: test1284.o ../cups/libcups.a testbackend: testbackend.o ../cups/libcups.a echo Linking $@... $(CC) $(LDFLAGS) -o testbackend testbackend.o ../cups/libcups.a \ - $(SSLLIBS) $(COMMONLIBS) $(LIBZ) + $(LIBGSSAPI) $(SSLLIBS) $(COMMONLIBS) $(LIBZ) # diff --git a/backend/snmp.c b/backend/snmp.c index abfa6215a..4e0cd1d6f 100644 --- a/backend/snmp.c +++ b/backend/snmp.c @@ -85,7 +85,7 @@ * Community public * DebugLevel 0 * HostNameLookups off - * MaxRunTime 10 + * MaxRunTime 120 * * This backend is known to work with the following network printers and * print servers: @@ -181,7 +181,7 @@ static int DeviceTypeOID[] = { CUPS_OID_hrDeviceType, 1, -1 }; static unsigned DeviceTypeRequest; static cups_array_t *DeviceURIs = NULL; static int HostNameLookups = 0; -static int MaxRunTime = 10; +static int MaxRunTime = 120; static struct timeval StartTime; @@ -657,11 +657,14 @@ static void list_device(snmp_cache_t *cache) /* I - Cached device */ { if (cache->uri) + { printf("network %s \"%s\" \"%s %s\" \"%s\"\n", cache->uri, cache->make_and_model ? cache->make_and_model : "Unknown", cache->make_and_model ? cache->make_and_model : "Unknown", cache->addrname, cache->id ? cache->id : ""); + fflush(stdout); + } } @@ -1013,6 +1016,8 @@ read_snmp_response(int fd) /* I - SNMP socket file descriptor */ free(device->make_and_model); device->make_and_model = strdup(make_model); + + probe_device(device); } } @@ -1109,13 +1114,13 @@ scan_devices(int fd) /* I - SNMP socket */ * Then read any responses that come in over the next 3 seconds... */ - endtime = time(NULL) + 3; + endtime = time(NULL) + MaxRunTime; FD_ZERO(&input); while (time(NULL) < endtime) { - timeout.tv_sec = 1; + timeout.tv_sec = 2; timeout.tv_usec = 0; FD_SET(fd, &input); diff --git a/backend/test1284.c b/backend/test1284.c index 62905e2df..bbb4f2c3f 100644 --- a/backend/test1284.c +++ b/backend/test1284.c @@ -34,7 +34,9 @@ # include #endif /* WIN32 */ -#define DEBUG +#ifndef DEBUG +# define DEBUG +#endif /* !DEBUG */ #include "ieee1284.c" diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index ab103c24d..f9197173e 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -1705,7 +1705,7 @@ static void setup_cfLanguage(void) langArray = CFArrayCreate(kCFAllocatorDefault, (const void **)lang, sizeof(lang) / sizeof(lang[0]), &kCFTypeArrayCallBacks); CFPreferencesSetAppValue(CFSTR("AppleLanguages"), langArray, kCFPreferencesCurrentApplication); - DEBUG_printf((stderr, "DEBUG: usb: AppleLanguages = \"%s\"\n", requestedLang)); + fprintf(stderr, "DEBUG: usb: AppleLanguages = \"%s\"\n", requestedLang); CFRelease(lang[0]); CFRelease(langArray); diff --git a/berkeley/lpq.c b/berkeley/lpq.c index 18b2e1ccd..7ffb2a8e9 100644 --- a/berkeley/lpq.c +++ b/berkeley/lpq.c @@ -3,7 +3,7 @@ * * "lpq" command for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -355,8 +355,8 @@ show_jobs(const char *command, /* I - Command name */ }; - DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id, - longstatus)); + DEBUG_printf(("show_jobs(http=%p, dest=%p, user=%p, id=%d, longstatus%d)\n", + http, dest, user, id, longstatus)); if (http == NULL) return (0); diff --git a/cgi-bin/help-index.c b/cgi-bin/help-index.c index b32f8a7af..64f1380ac 100644 --- a/cgi-bin/help-index.c +++ b/cgi-bin/help-index.c @@ -3,7 +3,7 @@ * * On-line help index routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -500,7 +500,7 @@ helpSaveIndex(help_index_t *hi, /* I - Index */ else { if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n", - node->filename, node->mtime, + node->filename, (int)node->mtime, CUPS_LLCAST node->offset, CUPS_LLCAST node->length, node->section ? node->section : "", node->text) < 0) break; diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 3ae98ca6c..596b24d0d 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -203,10 +203,10 @@ cgiGetVariable(const char *name) /* I - Name of variable */ #ifdef DEBUG if (var == NULL) - printf("cgiGetVariable(\"%s\") is returning NULL...\n", name); + DEBUG_printf(("cgiGetVariable(\"%s\") is returning NULL...\n", name)); else - printf("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name, - var->values[var->nvalues - 1]); + DEBUG_printf(("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name, + var->values[var->nvalues - 1])); #endif /* DEBUG */ return ((var == NULL) ? NULL : var->values[var->nvalues - 1]); @@ -242,7 +242,6 @@ cgiInitialize(void) */ setbuf(stdout, NULL); - puts("Content-type: text/plain\n"); #endif /* DEBUG */ /* @@ -444,9 +443,8 @@ cgi_add_variable(const char *name, /* I - Variable name */ if (name == NULL || value == NULL || element < 0 || element > 100000) return; -#ifdef DEBUG - printf("Adding variable \'%s\' with value \'%s\'...\n", name, value); -#endif /* DEBUG */ + DEBUG_printf(("cgi_add_variable: Adding variable \'%s\' with value " + "\'%s\'...\n", name, value)); if (form_count >= form_alloc) { @@ -522,9 +520,7 @@ cgi_initialize_get(void) char *data; /* Pointer to form data string */ -#ifdef DEBUG - puts("Initializing variables using GET method..."); -#endif /* DEBUG */ + DEBUG_puts("cgi_initialize_get: Initializing variables using GET method..."); /* * Check to see if there is anything for us to read... @@ -778,9 +774,7 @@ cgi_initialize_post(void) status; /* Return status */ -#ifdef DEBUG - puts("Initializing variables using POST method..."); -#endif /* DEBUG */ + DEBUG_puts("cgi_initialize_post: Initializing variables using POST method..."); /* * Check to see if there is anything for us to read... @@ -996,7 +990,7 @@ cgi_sort_variables(void) int i; - puts("Sorting variables..."); + DEBUG_puts("cgi_sort_variables: Sorting variables..."); #endif /* DEBUG */ if (form_count < 2) @@ -1006,10 +1000,11 @@ cgi_sort_variables(void) (int (*)(const void *, const void *))cgi_compare_variables); #ifdef DEBUG - puts("Sorted variable list is:"); + DEBUG_puts("cgi_sort_variables: Sorted variable list is:"); for (i = 0; i < form_count; i ++) - printf("%d: %s (%d) = \"%s\" ...\n", i, form_vars[i].name, - form_vars[i].nvalues, form_vars[i].values[0]); + DEBUG_printf(("cgi_sort_variables: %d: %s (%d) = \"%s\" ...\n", i, + form_vars[i].name, form_vars[i].nvalues, + form_vars[i].values[0])); #endif /* DEBUG */ } diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in index 40917e9b3..55b7c5ca8 100644 --- a/conf/cupsd.conf.in +++ b/conf/cupsd.conf.in @@ -53,7 +53,7 @@ DefaultAuthType Basic # All administration operations require an administrator to authenticate... - + AuthType Default Require user @SYSTEM Order deny,allow diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4 index 1fb08a520..4b1f83c8c 100644 --- a/config-scripts/cups-compiler.m4 +++ b/config-scripts/cups-compiler.m4 @@ -26,6 +26,7 @@ AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no]) dnl For debugging, keep symbols, otherwise strip them... if test x$enable_debug = xyes; then OPTIM="-g" + CFLAGS="$CFLAGS -DDEBUG" else INSTALL_STRIP="-s" fi diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4 index c09b99a98..b72631f4c 100644 --- a/config-scripts/cups-defaults.m4 +++ b/config-scripts/cups-defaults.m4 @@ -339,10 +339,10 @@ fi AC_DEFINE_UNQUOTED(CUPS_DEFAULT_SMB_CONFIG_FILE, "$CUPS_DEFAULT_SMB_CONFIG_FILE") dnl Default MaxCopies value... -AC_ARG_WITH(max-copies, [ --with-max-copies set max copies value, default=100 ], +AC_ARG_WITH(max-copies, [ --with-max-copies set default max copies value, default=auto ], CUPS_MAX_COPIES="$withval", if test "x$uname" = xDarwin; then - CUPS_MAX_COPIES="999" + CUPS_MAX_COPIES="9999" else CUPS_MAX_COPIES="100" fi) diff --git a/config-scripts/cups-pdf.m4 b/config-scripts/cups-pdf.m4 index 6e4ed8fb0..e980f1de5 100644 --- a/config-scripts/cups-pdf.m4 +++ b/config-scripts/cups-pdf.m4 @@ -3,7 +3,7 @@ dnl "$Id: cups-pdf.m4 6649 2007-07-11 21:46:42Z mike $" dnl dnl PDF filter configuration stuff for the Common UNIX Printing System (CUPS). dnl -dnl Copyright 2007 by Apple Inc. +dnl Copyright 2007-2008 by Apple Inc. dnl Copyright 2006 by Easy Software Products, all rights reserved. dnl dnl These coded instructions, statements, and computer programs are the @@ -19,9 +19,18 @@ PDFTOPS="" if test "x$enable_pdftops" != xno; then AC_PATH_PROG(CUPS_PDFTOPS, pdftops) + if test "x$CUPS_PDFTOPS" != x; then + AC_DEFINE(HAVE_PDFTOPS) + fi AC_DEFINE_UNQUOTED(CUPS_PDFTOPS, "$CUPS_PDFTOPS") - if test "x$CUPS_PDFTOPS" != x; then + AC_PATH_PROG(CUPS_GHOSTSCRIPT, gs) + if test "x$CUPS_GHOSTSCRIPT" != x; then + AC_DEFINE(HAVE_GHOSTSCRIPT) + fi + AC_DEFINE_UNQUOTED(CUPS_GHOSTSCRIPT, "$CUPS_GHOSTSCRIPT") + + if test "x$CUPS_PDFTOPS" != x -o "x$CUPS_GHOSTSCRIPT" != x; then AC_MSG_CHECKING(whether to build pdftops filter) if test x$enable_pdftops = xyes -o $uname != Darwin; then PDFTOPS="pdftops" @@ -30,7 +39,7 @@ if test "x$enable_pdftops" != xno; then AC_MSG_RESULT(no) fi elif test x$enable_pdftops = xyes; then - AC_MSG_ERROR(Unable to find pdftops program!) + AC_MSG_ERROR(Unable to find pdftops or gs programs!) exit 1 fi fi diff --git a/config.h.in b/config.h.in index fc9013137..5e0c08af1 100644 --- a/config.h.in +++ b/config.h.in @@ -3,7 +3,7 @@ * * Configuration file for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -434,9 +434,18 @@ * Location of the poppler/Xpdf pdftops program... */ +#undef HAVE_PDFTOPS #define CUPS_PDFTOPS "/usr/bin/pdftops" +/* + * Location of the Ghostscript gs program... + */ + +#undef HAVE_GHOSTSCRIPT +#define CUPS_GHOSTSCRIPT "/usr/bin/gs" + + /* * Do we have Darwin's CoreFoundation and SystemConfiguration frameworks? */ diff --git a/cups/Makefile b/cups/Makefile index 5e66a122b..3ea420681 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -29,11 +29,13 @@ LIBOBJS = \ backchannel.o \ backend.o \ custom.o \ + debug.o \ dest.o \ dir.o \ emit.o \ encode.o \ file.o \ + getdevices.o \ getifaddrs.o \ getputfile.o \ globals.o \ @@ -483,7 +485,7 @@ apihelp: mxmldoc --section "Programming" --title "CUPS API" \ --css ../doc/cups-printable.css \ --header api-cups.header --intro api-cups.shtml \ - cups.h dest.c getputfile.c language.c notify.c \ + cups.h dest.c language.c notify.c \ options.c tempfile.c usersys.c \ util.c >../doc/help/api-cups.html mxmldoc --section "Programming" --title "File and Directory APIs" \ @@ -498,9 +500,9 @@ apihelp: mxmldoc --section "Programming" --title "HTTP and IPP APIs" \ --css ../doc/cups-printable.css \ --header api-httpipp.header --intro api-httpipp.shtml \ - http.h ipp.h auth.c encode.c http.c http-addr.c \ - http-support.c ipp.c ipp-support.c md5passwd.c \ - request.c >../doc/help/api-httpipp.html + http.h ipp.h auth.c getdevices.c getputfile.c encode.c \ + http.c http-addr.c http-support.c ipp.c ipp-support.c \ + md5passwd.c request.c >../doc/help/api-httpipp.html mxmldoc --section "Programming" \ --title "Filter and Backend Programming" \ --css ../doc/cups-printable.css \ @@ -524,7 +526,7 @@ framedhelp: --section "Programming" --title "CUPS API" \ --css ../doc/cups-printable.css \ --header api-cups.header --intro api-cups.shtml \ - cups.h dest.c getputfile.c language.c notify.c \ + cups.h dest.c language.c notify.c \ options.c tempfile.c usersys.c \ util.c mxmldoc --framed api-filedir \ @@ -542,9 +544,9 @@ framedhelp: --section "Programming" --title "HTTP and IPP APIs" \ --css ../doc/cups-printable.css \ --header api-httpipp.header --intro api-httpipp.shtml \ - http.h ipp.h auth.c encode.c http.c http-addr.c \ - http-support.c ipp.c ipp-support.c md5passwd.c \ - request.c + http.h ipp.h auth.c getdevices.c getputfile.c encode.c \ + http.c http-addr.c http-support.c ipp.c ipp-support.c \ + md5passwd.c request.c mxmldoc --framed api-filter \ --section "Programming" \ --title "Filter and Backend Programming" \ diff --git a/cups/array.c b/cups/array.c index df1ae2e54..9d9790bd5 100644 --- a/cups/array.c +++ b/cups/array.c @@ -934,7 +934,7 @@ cups_array_add(cups_array_t *a, /* I - Array */ } #ifdef DEBUG else - printf("cups_array_add: append element at %d...\n", current); + DEBUG_printf(("cups_array_add: append element at %d...\n", current)); #endif /* DEBUG */ a->elements[current] = e; @@ -943,7 +943,8 @@ cups_array_add(cups_array_t *a, /* I - Array */ #ifdef DEBUG for (current = 0; current < a->num_elements; current ++) - printf("cups_array_add: a->elements[%d]=%p\n", current, a->elements[current]); + DEBUG_printf(("cups_array_add: a->elements[%d]=%p\n", current, + a->elements[current])); #endif /* DEBUG */ DEBUG_puts("cups_array_add: returning 1"); diff --git a/cups/auth.c b/cups/auth.c index 4391a3db0..d3d38b47e 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -328,7 +328,7 @@ cupsDoAuthentication(http_t *http, /* I - Connection to server or @code CUPS else { DEBUG_printf(("cupsDoAuthentication: Kerberos credentials too large - " - "%d bytes!\n", output_token.length)); + "%d bytes!\n", (int)output_token.length)); major_status = gss_release_buffer(&minor_status, &output_token); diff --git a/cups/cups.h b/cups/cups.h index fd8cc3aa3..4321a459e 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -65,6 +65,7 @@ extern "C" { # define CUPS_VERSION_PATCH -1 # define CUPS_DATE_ANY (time_t)-1 +# define CUPS_EXCLUDE_NONE (const char *)0 # define CUPS_FORMAT_AUTO "application/octet-stream" # define CUPS_FORMAT_PDF "application/pdf" # define CUPS_FORMAT_POSTSCRIPT "application/postscript" @@ -74,6 +75,7 @@ extern "C" { # define CUPS_JOBID_ALL -1 # define CUPS_JOBID_CURRENT 0 # define CUPS_LENGTH_VARIABLE (ssize_t)0 +# define CUPS_TIMEOUT_DEFAULT 0 # define CUPS_WHICHJOBS_ALL -1 # define CUPS_WHICHJOBS_ACTIVE 0 # define CUPS_WHICHJOBS_COMPLETED 1 @@ -115,9 +117,15 @@ enum cups_ptype_e /**** Printer type/capability bit constants ****/ CUPS_PRINTER_OPTIONS = 0x6fffc /* ~(CLASS | REMOTE | IMPLICIT | DEFAULT | FAX | REJECTING | DELETE | NOT_SHARED | AUTHENTICATED | COMMANDS | DISCOVERED) @private@ */ }; -typedef const char *(*cups_password_cb_t)(const char *); +typedef const char *(*cups_password_cb_t)(const char *prompt); /**** Password callback ****/ +typedef void (*cups_device_cb_t)(const char *device_class, + const char *device_id, const char *device_info, + const char *device_make_and_model, + const char *device_uri, void *user_data); + /**** Device callback @since CUPS 1.4@ ****/ + typedef struct cups_option_s /**** Printer Options ****/ { char *name; /* Name of option */ @@ -269,6 +277,10 @@ extern int cupsCreateJob(http_t *http, const char *name, cups_option_t *options) _CUPS_API_1_4; extern ipp_status_t cupsFinishDocument(http_t *http, const char *name) _CUPS_API_1_4; +extern ipp_status_t cupsGetDevices(http_t *http, int timeout, + const char *exclude_schemes, + cups_device_cb_t callback, + void *user_data) _CUPS_API_1_4; extern cups_dest_t *cupsGetNamedDest(http_t *http, const char *name, const char *instance) _CUPS_API_1_4; extern http_status_t cupsGetPPD3(http_t *http, const char *name, diff --git a/cups/debug.c b/cups/debug.c new file mode 100644 index 000000000..fcaa11e2a --- /dev/null +++ b/cups/debug.c @@ -0,0 +1,452 @@ +/* + * "$Id$" + * + * Debugging functions for the Common UNIX Printing System (CUPS). + * + * Copyright 2008 by Apple Inc. + * + * 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/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * _cups_debug_printf() - Write a formatted line to the log. + * _cups_debug_puts() - Write a single line to the log. + */ + +/* + * Include necessary headers... + */ + +#include "globals.h" +#include "debug.h" +#include +#include +#include + + +#ifdef DEBUG +/* + * 'debug_vsnprintf()' - Format a string into a fixed size buffer. + */ + +int /* O - Number of bytes formatted */ +debug_vsnprintf(char *buffer, /* O - Output buffer */ + size_t bufsize, /* O - Size of output buffer */ + const char *format, /* I - printf-style format string */ + va_list ap) /* I - Pointer to additional arguments */ +{ + char *bufptr, /* Pointer to position in buffer */ + *bufend, /* Pointer to end of buffer */ + sign, /* Sign of format width */ + size, /* Size character (h, l, L) */ + type; /* Format type character */ + int width, /* Width of field */ + prec; /* Number of characters of precision */ + char tformat[100], /* Temporary format string for sprintf() */ + *tptr, /* Pointer into temporary format */ + temp[1024]; /* Buffer for formatted numbers */ + char *s; /* Pointer to string */ + int bytes; /* Total number of bytes needed */ + + + /* + * Loop through the format string, formatting as needed... + */ + + bufptr = buffer; + bufend = buffer + bufsize - 1; + bytes = 0; + + while (*format) + { + if (*format == '%') + { + tptr = tformat; + *tptr++ = *format++; + + if (*format == '%') + { + if (bufptr && bufptr < bufend) *bufptr++ = *format; + bytes ++; + format ++; + continue; + } + else if (strchr(" -+#\'", *format)) + { + *tptr++ = *format; + sign = *format++; + } + else + sign = 0; + + if (*format == '*') + { + /* + * Get width from argument... + */ + + format ++; + width = va_arg(ap, int); + + snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width); + tptr += strlen(tptr); + } + else + { + width = 0; + + while (isdigit(*format & 255)) + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + width = width * 10 + *format++ - '0'; + } + } + + if (*format == '.') + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + format ++; + + if (*format == '*') + { + /* + * Get precision from argument... + */ + + format ++; + prec = va_arg(ap, int); + + snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec); + tptr += strlen(tptr); + } + else + { + prec = 0; + + while (isdigit(*format & 255)) + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + prec = prec * 10 + *format++ - '0'; + } + } + } + else + prec = -1; + + if (*format == 'l' && format[1] == 'l') + { + size = 'L'; + + if (tptr < (tformat + sizeof(tformat) - 2)) + { + *tptr++ = 'l'; + *tptr++ = 'l'; + } + + format += 2; + } + else if (*format == 'h' || *format == 'l' || *format == 'L') + { + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + size = *format++; + } + + if (!*format) + break; + + if (tptr < (tformat + sizeof(tformat) - 1)) + *tptr++ = *format; + + type = *format++; + *tptr = '\0'; + + switch (type) + { + case 'E' : /* Floating point formats */ + case 'G' : + case 'e' : + case 'f' : + case 'g' : + if ((width + 2) > sizeof(temp)) + break; + + sprintf(temp, tformat, va_arg(ap, double)); + + bytes += (int)strlen(temp); + + if (bufptr) + { + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'B' : /* Integer formats */ + case 'X' : + case 'b' : + case 'd' : + case 'i' : + case 'o' : + case 'u' : + case 'x' : + if ((width + 2) > sizeof(temp)) + break; + +#ifdef HAVE_LONG_LONG + if (size == 'L') + sprintf(temp, tformat, va_arg(ap, long long)); + else +#endif /* HAVE_LONG_LONG */ + if (size == 'l') + sprintf(temp, tformat, va_arg(ap, long)); + else + sprintf(temp, tformat, va_arg(ap, int)); + + bytes += (int)strlen(temp); + + if (bufptr) + { + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'p' : /* Pointer value */ + if ((width + 2) > sizeof(temp)) + break; + + sprintf(temp, tformat, va_arg(ap, void *)); + + bytes += (int)strlen(temp); + + if (bufptr) + { + if ((bufptr + strlen(temp)) > bufend) + { + strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr = bufend; + } + else + { + strcpy(bufptr, temp); + bufptr += strlen(temp); + } + } + break; + + case 'c' : /* Character or character array */ + bytes += width; + + if (bufptr) + { + if (width <= 1) + *bufptr++ = va_arg(ap, int); + else + { + if ((bufptr + width) > bufend) + width = (int)(bufend - bufptr); + + memcpy(bufptr, va_arg(ap, char *), (size_t)width); + bufptr += width; + } + } + break; + + case 's' : /* String */ + if ((s = va_arg(ap, char *)) == NULL) + s = "(null)"; + + /* + * Copy the C string, replacing control chars and \ with + * C character escapes... + */ + + for (bufend --; *s && bufptr < bufend; s ++) + { + if (*s == '\n') + { + *bufptr++ = '\\'; + *bufptr++ = 'n'; + } + else if (*s == '\r') + { + *bufptr++ = '\\'; + *bufptr++ = 'r'; + } + else if (*s == '\t') + { + *bufptr++ = '\\'; + *bufptr++ = 't'; + } + else if (*s == '\\') + { + *bufptr++ = '\\'; + *bufptr++ = '\\'; + } + else if (*s == '\'') + { + *bufptr++ = '\\'; + *bufptr++ = '\''; + } + else if (*s == '\"') + { + *bufptr++ = '\\'; + *bufptr++ = '\"'; + } + else if ((*s & 255) < ' ') + { + *bufptr++ = '\\'; + *bufptr++ = '0'; + *bufptr++ = '0' + *s / 8; + *bufptr++ = '0' + (*s & 7); + } + else + *bufptr++ = *s; + } + + bufend ++; + break; + + case 'n' : /* Output number of chars so far */ + *(va_arg(ap, int *)) = bytes; + break; + } + } + else + { + bytes ++; + + if (bufptr && bufptr < bufend) + *bufptr++ = *format; + + format ++; + } + } + + /* + * Nul-terminate the string and return the number of characters needed. + */ + + *bufptr = '\0'; + + return (bytes); +} + + +/* + * '_cups_debug_printf()' - Write a formatted line to the log. + */ + +void +_cups_debug_printf(const char *format, /* I - Printf-style format string */ + ...) /* I - Additional arguments as needed */ +{ + va_list ap; /* Pointer to arguments */ + struct timeval curtime; /* Current time */ + char buffer[2048]; /* Output buffer */ + size_t bytes; /* Number of bytes in buffer */ + const char *cups_debug_log;/* CUPS_DEBUG_LOG environment variable */ + _cups_globals_t *cg = _cupsGlobals(); + /* Global data */ + + + /* + * See if we need to do any logging... + */ + + if (!cg->debug_init) + { + cg->debug_init = 1; + + if ((cups_debug_log = getenv("CUPS_DEBUG_LOG")) == NULL) + cg->debug_fd = -1; + else if (!strcmp(cups_debug_log, "-")) + cg->debug_fd = 2; + else + cg->debug_fd = open(cups_debug_log, O_WRONLY | O_APPEND | O_CREAT, 0644); + } + + if (cg->debug_fd < 0) + return; + + /* + * Format the message... + */ + + gettimeofday(&curtime, NULL); + snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d.%03d ", + (int)((curtime.tv_sec / 3600) % 24), + (int)((curtime.tv_sec / 60) % 60), + (int)(curtime.tv_sec % 60), (int)(curtime.tv_usec / 1000)); + + va_start(ap, format); + debug_vsnprintf(buffer + 13, sizeof(buffer) - 14, format, ap); + va_end(ap); + + bytes = strlen(buffer); + if (buffer[bytes - 1] != '\n') + { + buffer[bytes] = '\n'; + bytes ++; + buffer[bytes] = '\0'; + } + + /* + * Write it out... + */ + + write(cg->debug_fd, buffer, bytes); +} + + +/* + * '_cups_debug_puts()' - Write a single line to the log. + */ + +void +_cups_debug_puts(const char *s) /* I - String to output */ +{ + _cups_debug_printf("%s\n", s); +} + + +#elif defined(__APPLE__) +/* Mac OS X needs these stubbed since we reference them in the libcups.exp file */ +void _cups_debug_printf(const char *format, ...) {} +void _cups_debug_puts(const char *s) {} +#endif /* DEBUG */ + + +/* + * End of "$Id$". + */ diff --git a/cups/debug.h b/cups/debug.h index 074384b65..756c4773d 100644 --- a/cups/debug.h +++ b/cups/debug.h @@ -3,7 +3,7 @@ * * Debugging macros for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -18,12 +18,6 @@ #ifndef _CUPS_DEBUG_H_ # define _CUPS_DEBUG_H_ -/* - * Include necessary headers... - */ - -# include - /* * The debug macros are used if you compile with DEBUG defined. * @@ -36,13 +30,26 @@ */ # ifdef DEBUG -# define DEBUG_puts(x) puts(x) -# define DEBUG_printf(x) printf x +# define DEBUG_puts(x) _cups_debug_puts(x) +# define DEBUG_printf(x) _cups_debug_printf x # else # define DEBUG_puts(x) # define DEBUG_printf(x) # endif /* DEBUG */ + +/* + * Prototypes... + */ + +extern void _cups_debug_printf(const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 1, 2))) +#endif /* __GNUC__ */ +; +extern void _cups_debug_puts(const char *s); + + #endif /* !_CUPS_DEBUG_H_ */ /* diff --git a/cups/dest.c b/cups/dest.c index bafe52f14..a4c826413 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -965,7 +965,7 @@ appleGetDefault(char *name, /* I - Name buffer */ #ifdef DEBUG CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); - printf("appleGetDefault: network=\"%s\"\n", name); + DEBUG_printf(("appleGetDefault: network=\"%s\"\n", name)); #endif /* DEBUG */ /* diff --git a/cups/emit.c b/cups/emit.c index 494b1d45e..da76ea36e 100644 --- a/cups/emit.c +++ b/cups/emit.c @@ -667,7 +667,8 @@ ppdEmitString(ppd_file_t *ppd, /* I - PPD file record */ * Allocate memory... */ - DEBUG_printf(("ppdEmitString: Allocating %d bytes for string...\n", bufsize)); + DEBUG_printf(("ppdEmitString: Allocating %d bytes for string...\n", + (int)bufsize)); if ((buffer = calloc(1, bufsize)) == NULL) { @@ -894,7 +895,7 @@ ppdEmitString(ppd_file_t *ppd, /* I - PPD file record */ bufptr += strlen(bufptr); DEBUG_printf(("ppdEmitString: Offset in string is %d...\n", - bufptr - buffer)); + (int)(bufptr - buffer))); } else { diff --git a/cups/encode.c b/cups/encode.c index 0fb288b1a..335623eae 100644 --- a/cups/encode.c +++ b/cups/encode.c @@ -55,6 +55,7 @@ static const _ipp_option_t ipp_options[] = { 0, "copies-default", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, { 0, "document-format", IPP_TAG_MIMETYPE, IPP_TAG_OPERATION }, { 0, "document-format-default", IPP_TAG_MIMETYPE, IPP_TAG_PRINTER }, + { 1, "exclude-schemes", IPP_TAG_NAME, IPP_TAG_OPERATION }, { 1, "finishings", IPP_TAG_ENUM, IPP_TAG_JOB }, { 1, "finishings-default", IPP_TAG_ENUM, IPP_TAG_PRINTER }, { 0, "fitplot", IPP_TAG_BOOLEAN, IPP_TAG_JOB }, @@ -125,6 +126,7 @@ static const _ipp_option_t ipp_options[] = { 0, "printer-uri", IPP_TAG_URI, IPP_TAG_OPERATION }, { 0, "queued-job-count", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, { 0, "raw", IPP_TAG_MIMETYPE, IPP_TAG_OPERATION }, + { 1, "requested-attributes", IPP_TAG_NAME, IPP_TAG_OPERATION }, { 1, "requesting-user-name-allowed", IPP_TAG_NAME, IPP_TAG_PRINTER }, { 1, "requesting-user-name-denied", IPP_TAG_NAME, IPP_TAG_PRINTER }, { 0, "resolution", IPP_TAG_RESOLUTION, IPP_TAG_JOB }, @@ -522,8 +524,8 @@ cupsEncodeOptions2( attr->values[j].unknown.length = (int)strlen(val); attr->values[j].unknown.data = strdup(val); - DEBUG_printf(("cupsEncodeOptions2: Added octet-string value \"%s\"...\n", - attr->values[j].unknown.data)); + DEBUG_printf(("cupsEncodeOptions2: Added octet-string value " + "\"%s\"...\n", (char *)attr->values[j].unknown.data)); break; default : diff --git a/cups/file.h b/cups/file.h index a73d8fa58..05a32cc71 100644 --- a/cups/file.h +++ b/cups/file.h @@ -81,7 +81,11 @@ extern int cupsFileNumber(cups_file_t *fp) _CUPS_API_1_2; extern cups_file_t *cupsFileOpen(const char *filename, const char *mode) _CUPS_API_1_2; extern cups_file_t *cupsFileOpenFd(int fd, const char *mode) _CUPS_API_1_2; extern int cupsFilePeekChar(cups_file_t *fp) _CUPS_API_1_2; -extern int cupsFilePrintf(cups_file_t *fp, const char *format, ...) _CUPS_API_1_2; +extern int cupsFilePrintf(cups_file_t *fp, const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +#endif /* __GNUC__ */ +_CUPS_API_1_2; extern int cupsFilePutChar(cups_file_t *fp, int c) _CUPS_API_1_2; extern int cupsFilePuts(cups_file_t *fp, const char *s) _CUPS_API_1_2; extern ssize_t cupsFileRead(cups_file_t *fp, char *buf, size_t bytes) _CUPS_API_1_2; diff --git a/cups/getdevices.c b/cups/getdevices.c new file mode 100644 index 000000000..6843e5afd --- /dev/null +++ b/cups/getdevices.c @@ -0,0 +1,259 @@ +/* + * "$Id$" + * + * cupsGetDevices implementation for the Common UNIX Printing System (CUPS). + * + * Copyright 2008 by Apple Inc. + * + * 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/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + */ + +/* + * Include necessary headers... + */ + +#include "globals.h" +#include "debug.h" + + +/* + * 'cupsGetDevices()' - Get available printer devices. + * + * This function sends a CUPS-Get-Devices request and streams the discovered + * devices to the specified callback function. The "timeout" parameter controls + * how long the request lasts, while the "exclude_schemes" parameter provides + * a comma-delimited list of backends to omit from the request. + * + * @since CUPS 1.4@ + */ + +ipp_status_t /* O - Request status - @code IPP_OK@ on success. */ +cupsGetDevices( + http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ + int timeout, /* I - Timeout in seconds or @code CUPS_TIMEOUT_DEFAULT@ */ + const char *exclude_schemes, /* I - Comma-separated URI schemes to exclude or @code CUPS_EXCLUDE_NONE@ */ + cups_device_cb_t callback, /* I - Callback function */ + void *user_data) /* I - User data pointer */ +{ + ipp_t *request, /* CUPS-Get-Devices request */ + *response; /* CUPS-Get-Devices response */ + ipp_attribute_t *attr; /* Current attribute */ + const char *device_class, /* device-class value */ + *device_id, /* device-id value */ + *device_info, /* device-info value */ + *device_make_and_model, /* device-make-and-model value */ + *device_uri; /* device-uri value */ + int blocking; /* Current blocking-IO mode */ + cups_option_t option; /* exclude-schemes option */ + http_status_t status; /* HTTP status of request */ + ipp_state_t state; /* IPP response state */ + + + /* + * Range check input... + */ + + if (!callback) + return (IPP_INTERNAL_ERROR); + + if (!http) + http = _cupsConnect(); + + if (!http) + return (IPP_SERVICE_UNAVAILABLE); + + /* + * Create a CUPS-Get-Devices request... + */ + + request = ippNewRequest(CUPS_GET_DEVICES); + + if (timeout > 0) + ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout", + timeout); + + if (exclude_schemes) + { + option.name = "exclude-schemes"; + option.value = (char *)exclude_schemes; + + cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); + } + + /* + * Send the request and do any necessary authentication... + */ + + do + { + DEBUG_puts("cupsGetDevices: Sending request..."); + status = cupsSendRequest(http, request, "/", ippLength(request)); + + DEBUG_puts("cupsGetDevices: Waiting for response status..."); + while (status == HTTP_CONTINUE) + status = httpUpdate(http); + + if (status != HTTP_OK) + { + httpFlush(http); + + if (status == HTTP_UNAUTHORIZED) + { + /* + * See if we can do authentication... + */ + + int auth_result; + + DEBUG_puts("cupsGetDevices: Need authorization..."); + + if ((auth_result = cupsDoAuthentication(http, "POST", "/")) == 0) + httpReconnect(http); + else if (auth_result < 0) + http->status = status = HTTP_FORBIDDEN; + } + +#ifdef HAVE_SSL + else if (status == HTTP_UPGRADE_REQUIRED) + { + /* + * Force a reconnect with encryption... + */ + + DEBUG_puts("cupsGetDevices: Need encryption..."); + + if (!httpReconnect(http)) + httpEncryption(http, HTTP_ENCRYPT_REQUIRED); + } +#endif /* HAVE_SSL */ + } + } + while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED); + + DEBUG_printf(("cupsGetDevices: status=%d\n", status)); + + ippDelete(request); + + if (status != HTTP_OK) + { + _cupsSetHTTPError(status); + return (cupsLastError()); + } + + /* + * Read the response in non-blocking mode... + */ + + blocking = httpGetBlocking(http); + httpBlocking(http, 0); + + response = ippNew(); + device_class = NULL; + device_id = NULL; + device_info = NULL; + device_make_and_model = NULL; + device_uri = NULL; + attr = NULL; + + DEBUG_puts("cupsGetDevices: Reading response..."); + + do + { + if ((state = ippRead(http, response)) == IPP_ERROR) + break; + + DEBUG_printf(("cupsGetDevices: state=%d, response->last=%p\n", state, + response->last)); + + if (!response->attrs) + continue; + + while (attr != response->last) + { + if (!attr) + attr = response->attrs; + else + attr = attr->next; + + DEBUG_printf(("cupsGetDevices: attr->name=\"%s\", attr->value_tag=%d\n", + attr->name ? attr->name : "(null)", attr->value_tag)); + + if (!attr->name) + { + if (device_class && device_id && device_info && device_make_and_model && + device_uri) + (*callback)(device_class, device_id, device_info, + device_make_and_model, device_uri, user_data); + + device_class = NULL; + device_id = NULL; + device_info = NULL; + device_make_and_model = NULL; + device_uri = NULL; + } + else if (!strcmp(attr->name, "device-class") && + attr->value_tag == IPP_TAG_KEYWORD) + device_class = attr->values[0].string.text; + else if (!strcmp(attr->name, "device-id") && + attr->value_tag == IPP_TAG_TEXT) + device_id = attr->values[0].string.text; + else if (!strcmp(attr->name, "device-info") && + attr->value_tag == IPP_TAG_TEXT) + device_info = attr->values[0].string.text; + else if (!strcmp(attr->name, "device-make-and-model") && + attr->value_tag == IPP_TAG_TEXT) + device_make_and_model = attr->values[0].string.text; + else if (!strcmp(attr->name, "device-uri") && + attr->value_tag == IPP_TAG_URI) + device_uri = attr->values[0].string.text; + } + } + while (state != IPP_DATA); + + DEBUG_printf(("cupsGetDevices: state=%d, response->last=%p\n", state, + response->last)); + + if (device_class && device_id && device_info && device_make_and_model && + device_uri) + (*callback)(device_class, device_id, device_info, + device_make_and_model, device_uri, user_data); + + /* + * Set the IPP status and return... + */ + + httpBlocking(http, blocking); + + if (status == IPP_ERROR) + _cupsSetError(IPP_ERROR, NULL); + else + { + attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT); + + DEBUG_printf(("cupsGetDevices: status-code=%s, status-message=\"%s\"\n", + ippErrorString(response->request.status.status_code), + attr ? attr->values[0].string.text : "")); + + _cupsSetError(response->request.status.status_code, + attr ? attr->values[0].string.text : + ippErrorString(response->request.status.status_code)); + } + + ippDelete(response); + + return (cupsLastError()); +} + + +/* + * End of "$Id$". + */ diff --git a/cups/globals.c b/cups/globals.c index 53dcb0985..6849f424c 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -3,7 +3,7 @@ * * Global variable access routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -28,7 +28,6 @@ #include "http-private.h" #include "globals.h" -#include "debug.h" #include @@ -93,8 +92,6 @@ _cupsGlobals(void) * Initialize the global data exactly once... */ - DEBUG_printf(("_cupsGlobals(): globals_key_once=%d\n", globals_key_once)); - pthread_once(&globals_key_once, globals_init); /* @@ -103,8 +100,6 @@ _cupsGlobals(void) if ((globals = (_cups_globals_t *)pthread_getspecific(globals_key)) == NULL) { - DEBUG_puts("_cupsGlobals: allocating memory for thread..."); - /* * No, allocate memory as set the pointer for the key... */ @@ -112,8 +107,6 @@ _cupsGlobals(void) globals = calloc(1, sizeof(_cups_globals_t)); pthread_setspecific(globals_key, globals); - DEBUG_printf((" globals=%p\n", globals)); - /* * Initialize variables that have non-zero values */ @@ -140,9 +133,6 @@ static void globals_init() { pthread_key_create(&globals_key, globals_destructor); - - DEBUG_printf(("globals_init(): globals_key=%x(%u)\n", globals_key, - globals_key)); } @@ -157,8 +147,6 @@ globals_destructor(void *value) /* I - Data to free */ _cups_globals_t *cg; /* Global data */ - DEBUG_printf(("globals_destructor(value=%p)\n", value)); - cg = (_cups_globals_t *)value; httpClose(cg->http); diff --git a/cups/globals.h b/cups/globals.h index 0aacc0cc8..a735f01ab 100644 --- a/cups/globals.h +++ b/cups/globals.h @@ -64,6 +64,12 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/ /* Number of server settings */ cups_option_t *cupsd_settings;/* Server settings */ +#ifdef DEBUG + /* debug.c */ + int debug_init, /* Did we initialize debugging? */ + debug_fd; /* Debug log file descriptor */ +#endif /* DEBUG */ + /* file.c */ cups_file_t *stdio_files[3];/* stdin, stdout, stderr */ diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index 6fc5a1243..6d645053c 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -177,16 +177,17 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p #ifdef DEBUG - printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, service=\"%s\")\n", - hostname ? hostname : "(nil)", - family == AF_UNSPEC ? "UNSPEC" : + _cups_debug_printf("httpAddrGetList(hostname=\"%s\", family=AF_%s, " + "service=\"%s\")\n", + hostname ? hostname : "(nil)", + family == AF_UNSPEC ? "UNSPEC" : # ifdef AF_LOCAL - family == AF_LOCAL ? "LOCAL" : + family == AF_LOCAL ? "LOCAL" : # endif /* AF_LOCAL */ # ifdef AF_INET6 - family == AF_INET6 ? "INET6" : + family == AF_INET6 ? "INET6" : # endif /* AF_INET6 */ - family == AF_INET ? "INET" : "???", service); + family == AF_INET ? "INET" : "???", service); #endif /* DEBUG */ /* diff --git a/cups/http.c b/cups/http.c index e48c174c6..dabf218ce 100644 --- a/cups/http.c +++ b/cups/http.c @@ -77,6 +77,7 @@ * http_bio_puts() - Send a string for OpenSSL. * http_bio_read() - Read data for OpenSSL. * http_bio_write() - Write data for OpenSSL. + * http_debug_hex() - Do a hex dump of a buffer. * http_field() - Return the field index for a field name. * http_read_ssl() - Read from a SSL/TLS connection. * http_send() - Send a request with all fields and the trailing @@ -123,6 +124,10 @@ * Local functions... */ +#ifdef DEBUG +static void http_debug_hex(const char *prefix, const char *buffer, + int bytes); +#endif /* DEBUG */ static http_field_t http_field(const char *name); static int http_send(http_t *http, http_state_t request, const char *uri); @@ -1292,7 +1297,7 @@ httpRead2(http_t *http, /* I - Connection to server */ char len[32]; /* Length string */ - DEBUG_printf(("httpRead(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n", + DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n", http, buffer, CUPS_LLCAST length)); if (http == NULL || buffer == NULL) @@ -1488,35 +1493,7 @@ httpRead2(http_t *http, /* I - Connection to server */ } #ifdef DEBUG - { - int i, j, ch; - printf("httpRead2: Read " CUPS_LLFMT " bytes:\n", CUPS_LLCAST bytes); - for (i = 0; i < bytes; i += 16) - { - printf(" "); - - for (j = 0; j < 16 && (i + j) < bytes; j ++) - printf(" %02X", buffer[i + j] & 255); - - while (j < 16) - { - printf(" "); - j ++; - } - - printf(" "); - for (j = 0; j < 16 && (i + j) < bytes; j ++) - { - ch = buffer[i + j] & 255; - - if (ch < ' ' || ch >= 127) - ch = '.'; - - putchar(ch); - } - putchar('\n'); - } - } + http_debug_hex("httpRead2", buffer, (int)bytes); #endif /* DEBUG */ return (bytes); @@ -2125,7 +2102,7 @@ httpWrite2(http_t *http, /* I - Connection to server */ ssize_t bytes; /* Bytes written */ - DEBUG_printf(("httpWrite(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n", http, + DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n", http, buffer, CUPS_LLCAST length)); /* @@ -2149,8 +2126,8 @@ httpWrite2(http_t *http, /* I - Connection to server */ { if (http->wused && (length + http->wused) > sizeof(http->wbuffer)) { - DEBUG_printf((" flushing buffer (wused=%d, length=" CUPS_LLFMT ")\n", - http->wused, CUPS_LLCAST length)); + DEBUG_printf(("httpWrite2: Flushing buffer (wused=%d, length=" + CUPS_LLFMT ")\n", http->wused, CUPS_LLCAST length)); httpFlushWrite(http); } @@ -2161,7 +2138,7 @@ httpWrite2(http_t *http, /* I - Connection to server */ * Write to buffer... */ - DEBUG_printf((" copying " CUPS_LLFMT " bytes to wbuffer...\n", + DEBUG_printf(("httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...\n", CUPS_LLCAST length)); memcpy(http->wbuffer + http->wused, buffer, length); @@ -2174,7 +2151,7 @@ httpWrite2(http_t *http, /* I - Connection to server */ * Otherwise write the data directly... */ - DEBUG_printf((" writing " CUPS_LLFMT " bytes to socket...\n", + DEBUG_printf(("httpWrite2: Writing " CUPS_LLFMT " bytes to socket...\n", CUPS_LLCAST length)); if (http->data_encoding == HTTP_ENCODE_CHUNKED) @@ -2182,7 +2159,8 @@ httpWrite2(http_t *http, /* I - Connection to server */ else bytes = (ssize_t)http_write(http, buffer, (int)length); - DEBUG_printf((" wrote " CUPS_LLFMT " bytes...\n", CUPS_LLCAST bytes)); + DEBUG_printf(("httpWrite2: Wrote " CUPS_LLFMT " bytes...\n", + CUPS_LLCAST bytes)); } if (http->data_encoding == HTTP_ENCODE_LENGTH) @@ -2446,14 +2424,68 @@ http_bio_write(BIO *h, /* I - BIO data */ #endif /* HAVE_SSL && HAVE_LIBSSL */ +#ifdef DEBUG +/* + * 'http_debug_hex()' - Do a hex dump of a buffer. + */ + +static void +http_debug_hex(const char *prefix, /* I - Prefix for line */ + const char *buffer, /* I - Buffer to dump */ + int bytes) /* I - Bytes to dump */ +{ + int i, j, /* Looping vars */ + ch; /* Current character */ + char line[255], /* Line buffer */ + *start, /* Start of line after prefix */ + *ptr; /* Pointer into line */ + + + DEBUG_printf(("%s: %d bytes:\n", prefix, bytes)); + + snprintf(line, sizeof(line), "%s: ", prefix); + start = line + strlen(line); + + for (i = 0; i < bytes; i += 16) + { + for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2) + sprintf(ptr, "%02X", buffer[i + j] & 255); + + while (j < 16) + { + strcpy(ptr, " "); + ptr += 2; + j ++; + } + + strcpy(ptr, " "); + ptr += 2; + + for (j = 0; j < 16 && (i + j) < bytes; j ++) + { + ch = buffer[i + j] & 255; + + if (ch < ' ' || ch >= 127) + ch = '.'; + + *ptr++ = ch; + } + + *ptr = '\0'; + DEBUG_puts(line); + } +} +#endif /* DEBUG */ + + /* * 'http_field()' - Return the field index for a field name. */ -static http_field_t /* O - Field index */ -http_field(const char *name) /* I - String name */ +static http_field_t /* O - Field index */ +http_field(const char *name) /* I - String name */ { - int i; /* Looping var */ + int i; /* Looping var */ for (i = 0; i < HTTP_FIELD_MAX; i ++) @@ -2609,7 +2641,8 @@ http_send(http_t *http, /* I - Connection to server */ for (i = 0; i < HTTP_FIELD_MAX; i ++) if (http->fields[i][0] != '\0') { - DEBUG_printf(("%s: %s\n", http_fields[i], httpGetField(http, i))); + DEBUG_printf(("http_send: %s: %s\n", http_fields[i], + httpGetField(http, i))); if (httpPrintf(http, "%s: %s\r\n", http_fields[i], httpGetField(http, i)) < 1) @@ -3100,35 +3133,7 @@ http_write(http_t *http, /* I - Connection to server */ } #ifdef DEBUG - { - int i, j, ch; - printf("http_write: wrote %d bytes: \n", tbytes); - for (i = 0, buffer -= tbytes; i < tbytes; i += 16) - { - printf(" "); - - for (j = 0; j < 16 && (i + j) < tbytes; j ++) - printf(" %02X", buffer[i + j] & 255); - - while (j < 16) - { - printf(" "); - j ++; - } - - printf(" "); - for (j = 0; j < 16 && (i + j) < tbytes; j ++) - { - ch = buffer[i + j] & 255; - - if (ch < ' ' || ch == 127) - ch = '.'; - - putchar(ch); - } - putchar('\n'); - } - } + http_debug_hex("http_write", buffer - tbytes, tbytes); #endif /* DEBUG */ return (tbytes); diff --git a/cups/ipp-support.c b/cups/ipp-support.c index eaf485002..945dc4f63 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -325,7 +325,7 @@ ippPort(void) #ifdef DEBUG if (cg->ipp_port) - puts("ippPort: Set via cupsServer()..."); + DEBUG_puts(("ippPort: Set via cupsServer()...")); #endif /* DEBUG */ } diff --git a/cups/ipp.c b/cups/ipp.c index 9a5e0931e..0749ec2a1 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -982,10 +982,11 @@ ippRead(http_t *http, /* I - HTTP connection */ if (http == NULL) return (IPP_ERROR); - DEBUG_printf(("http->state = %d\n", http->state)); + DEBUG_printf(("ippRead: http->state=%d, http->used=%d\n", http->state, + http->used)); - return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, - http->blocking || http->used != 0, NULL, ipp)); + return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL, + ipp)); } @@ -1030,8 +1031,8 @@ ippReadIO(void *src, /* I - Data source */ ipp_value_t *value; /* Current value */ - DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src, cb, blocking, - parent, ipp)); + DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)\n", + src, cb, blocking, parent, ipp)); DEBUG_printf(("ippReadIO: ipp->state=%d\n", ipp->state)); if (src == NULL || ipp == NULL) @@ -2632,8 +2633,8 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ if (!attr->name) continue; - DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n", - attr->name, attr->num_values, bytes)); + DEBUG_printf(("ipp_length: attr->name=\"%s\", attr->num_values=%d, " + "bytes=%d\n", attr->name, attr->num_values, bytes)); bytes += (int)strlen(attr->name); /* Name */ bytes += attr->num_values; /* Value tag for each value */ @@ -2723,7 +2724,7 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ else bytes ++; - DEBUG_printf(("bytes = %d\n", bytes)); + DEBUG_printf(("ipp_length: bytes=%d\n", bytes)); return (bytes); } @@ -2750,9 +2751,12 @@ ipp_read_http(http_t *http, /* I - Client connection */ * Loop until all bytes are read... */ - for (tbytes = 0, bytes = 0; tbytes < (int)length; tbytes += bytes, buffer += bytes) + for (tbytes = 0, bytes = 0; + tbytes < (int)length; + tbytes += bytes, buffer += bytes) { - DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes, http->state)); + DEBUG_printf(("ipp_read_http: tbytes=%d, http->state=%d\n", tbytes, + http->state)); if (http->state == HTTP_WAITING) break; @@ -2840,7 +2844,7 @@ ipp_read_http(http_t *http, /* I - Client connection */ if (tbytes == 0 && bytes < 0) tbytes = -1; - DEBUG_printf(("returning %d bytes...\n", tbytes)); + DEBUG_printf(("ipp_read_http: returning %d bytes...\n", tbytes)); return (tbytes); } diff --git a/cups/language.c b/cups/language.c index e08bde626..eb041b0ca 100644 --- a/cups/language.c +++ b/cups/language.c @@ -723,7 +723,8 @@ cupsLangGet(const char *language) /* I - Language or locale */ * No generic localization, so use POSIX... */ - DEBUG_printf(("access(\"%s\", 0): %s\n", filename, strerror(errno))); + DEBUG_printf(("cupsLangGet: access(\"%s\", 0): %s\n", filename, + strerror(errno))); snprintf(filename, sizeof(filename), "%s/C/cups_C.po", cg->localedir); } diff --git a/cups/libcups.exp b/cups/libcups.exp index 8271f59ac..4a689e384 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -1,3 +1,5 @@ +__cups_debug_printf +__cups_debug_puts __cups_strcpy __cupsAdminGetServerSettings __cupsAdminSetServerSettings @@ -118,6 +120,7 @@ _cupsGetDefault2 _cupsGetDest _cupsGetDests _cupsGetDests2 +_cupsGetDevices _cupsGetFd _cupsGetFile _cupsGetJobs diff --git a/cups/localize.c b/cups/localize.c index fc981e2d1..17453961c 100644 --- a/cups/localize.c +++ b/cups/localize.c @@ -607,10 +607,10 @@ _ppdLocalizedAttr(ppd_file_t *ppd, /* I - PPD file */ #ifdef DEBUG if (attr) - printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec, attr->text, - attr->value ? attr->value : ""); + DEBUG_printf(("_ppdLocalizedAttr: *%s %s/%s: \"%s\"\n", attr->name, + attr->spec, attr->text, attr->value ? attr->value : "")); else - puts(" NOT FOUND"); + DEBUG_puts("_ppdLocalizedAttr: NOT FOUND"); #endif /* DEBUG */ return (attr); diff --git a/cups/mark.c b/cups/mark.c index 0dbb0b8d1..c0fdc911d 100644 --- a/cups/mark.c +++ b/cups/mark.c @@ -1018,12 +1018,12 @@ debug_marked(ppd_file_t *ppd, /* I - PPD file data */ ppd_choice_t *c; /* Current choice */ - printf("cupsMarkOptions: %s\n", title); + DEBUG_printf(("cupsMarkOptions: %s\n", title)); for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked); c; c = (ppd_choice_t *)cupsArrayNext(ppd->marked)) - printf("cupsMarkOptions: %s=%s\n", c->option->keyword, c->choice); + DEBUG_printf(("cupsMarkOptions: %s=%s\n", c->option->keyword, c->choice)); } #endif /* DEBUG */ diff --git a/cups/ppd.c b/cups/ppd.c index f8c714d13..f313c0f76 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -615,25 +615,9 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ while ((mask = ppd_read(fp, &line, keyword, name, text, &string, 1, cg)) != 0) { -#ifdef DEBUG - printf("mask = %x, keyword = \"%s\"", mask, keyword); - - if (name[0] != '\0') - printf(", name = \"%s\"", name); - - if (text[0] != '\0') - printf(", text = \"%s\"", text); - - if (string != NULL) - { - if (strlen(string) > 40) - printf(", string = %p", string); - else - printf(", string = \"%s\"", string); - } - - puts(""); -#endif /* DEBUG */ + DEBUG_printf(("mask=%x, keyword=\"%s\", name=\"%s\", text=\"%s\", " + "string=%d chars...", mask, keyword, name, text, + (int)strlen(string))); if (strcmp(keyword, "CloseUI") && strcmp(keyword, "CloseGroup") && strcmp(keyword, "CloseSubGroup") && strncmp(keyword, "Default", 7) && @@ -1199,7 +1183,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ * Add an option record to the current sub-group, group, or file... */ - DEBUG_printf(("name=\"%s\" (%d)\n", name, strlen(name))); + DEBUG_printf(("name=\"%s\" (%d)\n", name, (int)strlen(name))); if (name[0] == '*') _cups_strcpy(name, name + 1); /* Eliminate leading asterisk */ @@ -1933,7 +1917,8 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ #ifdef DEBUG if (!cupsFileEOF(fp)) - printf("Premature EOF at %lu...\n", (unsigned long)cupsFileTell(fp)); + DEBUG_printf(("Premature EOF at %lu...\n", + (unsigned long)cupsFileTell(fp))); #endif /* DEBUG */ if (cg->ppd_status != PPD_OK) @@ -2965,7 +2950,7 @@ ppd_read(cups_file_t *fp, /* I - File to read from */ *lineptr = '\0'; - DEBUG_printf(("LINE = \"%s\"\n", line)); + DEBUG_printf(("LINE=\"%s\"\n", line->buffer)); /* * The dynamically created PPDs for older style Mac OS X diff --git a/cups/request.c b/cups/request.c index 99cf9ff5a..e3465def0 100644 --- a/cups/request.c +++ b/cups/request.c @@ -420,7 +420,7 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP DEBUG_puts("cupsGetResponse: Need authorization..."); - if ((auth_result =cupsDoAuthentication(http, "POST", resource)) == 0) + if ((auth_result = cupsDoAuthentication(http, "POST", resource)) == 0) httpReconnect(http); else if (auth_result < 0) http->status = status = HTTP_FORBIDDEN; @@ -523,7 +523,7 @@ http_status_t /* O - Initial HTTP status */ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ ipp_t *request, /* I - IPP request */ const char *resource, /* I - Resource path */ - size_t length) /* I - Length of data to follow or CUPS_LENGTH_VARIABLE */ + size_t length) /* I - Length of data to follow or @code CUPS_LENGTH_VARIABLE@ */ { http_status_t status; /* Status of HTTP request */ int got_status; /* Did we get the status? */ diff --git a/cups/string.c b/cups/string.c index a20d0c507..c3ec0ef6b 100644 --- a/cups/string.c +++ b/cups/string.c @@ -175,8 +175,8 @@ _cupsStrFlush(void) _cups_sp_item_t *item; /* Current item */ - DEBUG_printf(("_cupsStrFlush(cg=%p)\n", cg)); - DEBUG_printf((" %d strings in array\n", cupsArrayCount(stringpool))); + DEBUG_printf(("_cupsStrFlush: %d strings in array\n", + cupsArrayCount(stringpool))); #ifdef HAVE_PTHREAD_H pthread_mutex_lock(&sp_mutex); diff --git a/cups/testfile.c b/cups/testfile.c index 6a0bd9057..3b9b9d515 100644 --- a/cups/testfile.c +++ b/cups/testfile.c @@ -3,7 +3,7 @@ * * File test program for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -34,6 +34,7 @@ #ifdef HAVE_LIBZ # include #endif /* HAVE_LIBZ */ +#include /* @@ -51,8 +52,10 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { - int status; /* Exit status */ - char filename[1024]; /* Filename buffer */ + int status; /* Exit status */ + char filename[1024]; /* Filename buffer */ + int fds[2]; /* Open file descriptors */ + cups_file_t *fdfile; /* File opened with cupsFileOpenFd() */ if (argc == 1) @@ -73,6 +76,40 @@ main(int argc, /* I - Number of command-line arguments */ status += read_write_tests(1); #endif /* HAVE_LIBZ */ + /* + * Test fdopen and close without reading... + */ + + pipe(fds); + close(fds[1]); + + fputs("cupsFileOpenFd(fd, \"r\"): ", stdout); + fflush(stdout); + + if ((fdfile = cupsFileOpenFd(fds[0], "r")) == NULL) + { + puts("FAIL"); + status ++; + } + else + { + /* + * Able to open file, now close without reading. If we don't return + * before the alarm fires, that is a failure and we will crash on the + * alarm signal... + */ + + puts("PASS"); + fputs("cupsFileClose(no read): ", stdout); + fflush(stdout); + + alarm(5); + cupsFileClose(fdfile); + alarm(0); + + puts("PASS"); + } + /* * Test path functions... */ diff --git a/cups/util.c b/cups/util.c index 7c7e4f406..ba9c62ee9 100644 --- a/cups/util.c +++ b/cups/util.c @@ -917,7 +917,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, " "bufsize=%d)\n", http, name ? name : "(null)", modtime, - modtime ? *modtime : 0, buffer, (int)bufsize)); + modtime ? (int)*modtime : 0, buffer, (int)bufsize)); if (!name) { diff --git a/doc/help/api-cups.html b/doc/help/api-cups.html index 654edaf27..b6eb2ab81 100644 --- a/doc/help/api-cups.html +++ b/doc/help/api-cups.html @@ -320,8 +320,6 @@ div.contents ul.subcontents li {
  • cupsGetDest
  • cupsGetDests
  • cupsGetDests2
  • -
  • cupsGetFd
  • -
  • cupsGetFile
  • cupsGetJobs
  • cupsGetJobs2
  • cupsGetNamedDest
  • @@ -351,8 +349,6 @@ server.">cupsPrintFile2 default server.">cupsPrintFiles
  • cupsPrintFiles2
  • -
  • cupsPutFd
  • -
  • cupsPutFile
  • cupsRemoveDest
  • cupsRemoveOption
  • cupsServer
  • @@ -371,6 +367,7 @@ specified server.">cupsPrintFiles2
  • Data Types
    • cups_dest_t
    • +
    • cups_device_cb_t
    • cups_job_t
    • cups_option_t
    • cups_password_cb_t
    • @@ -1170,52 +1167,6 @@ printer-state-reasons, and printer-type attributes as options.
      Use the cupsFreeDests function to free the destination list and the cupsGetDest function to find a particular destination. -

      -

       CUPS 1.1.20 cupsGetFd

      -

      Get a file from the server.

      -

      -http_status_t cupsGetFd (
      -    http_t *http,
      -    const char *resource,
      -    int fd
      -);

      -

      Parameters

      -
      -
      http
      -
      Connection to server or CUPS_HTTP_DEFAULT
      -
      resource
      -
      Resource name
      -
      fd
      -
      File descriptor
      -
      -

      Return Value

      -

      HTTP status

      -

      Discussion

      -

      This function returns HTTP_OK when the file is successfully retrieved. - -

      -

       CUPS 1.1.20 cupsGetFile

      -

      Get a file from the server.

      -

      -http_status_t cupsGetFile (
      -    http_t *http,
      -    const char *resource,
      -    const char *filename
      -);

      -

      Parameters

      -
      -
      http
      -
      Connection to server or CUPS_HTTP_DEFAULT
      -
      resource
      -
      Resource name
      -
      filename
      -
      Filename
      -
      -

      Return Value

      -

      HTTP status

      -

      Discussion

      -

      This function returns HTTP_OK when the file is successfully retrieved. -

      cupsGetJobs

      Get the jobs from the default server.

      @@ -1719,54 +1670,6 @@ int cupsPrintFiles2 (

      Return Value

      Job ID or 0 on error

      -

       CUPS 1.1.20 cupsPutFd

      -

      Put a file on the server.

      -

      -http_status_t cupsPutFd (
      -    http_t *http,
      -    const char *resource,
      -    int fd
      -);

      -

      Parameters

      -
      -
      http
      -
      Connection to server or CUPS_HTTP_DEFAULT
      -
      resource
      -
      Resource name
      -
      fd
      -
      File descriptor
      -
      -

      Return Value

      -

      HTTP status

      -

      Discussion

      -

      This function returns HTTP_CREATED when the file is stored -successfully. - -

      -

       CUPS 1.1.20 cupsPutFile

      -

      Put a file on the server.

      -

      -http_status_t cupsPutFile (
      -    http_t *http,
      -    const char *resource,
      -    const char *filename
      -);

      -

      Parameters

      -
      -
      http
      -
      Connection to server or CUPS_HTTP_DEFAULT
      -
      resource
      -
      Resource name
      -
      filename
      -
      Filename
      -
      -

      Return Value

      -

      HTTP status

      -

      Discussion

      -

      This function returns HTTP_CREATED when the file is stored -successfully. - -

       CUPS 1.3 cupsRemoveDest

      Remove a destination from the destination list.

      @@ -2049,6 +1952,11 @@ const char *cupsUser (void);

      typedef struct cups_dest_s cups_dest_t;

      +

       CUPS 1.4 cups_device_cb_t

      +

      Device callback

      +

      +typedef void (*cups_device_cb_t)(const char *device_class, const char *device_id, const char *device_info, const char *device_make_and_model, const char *device_uri, void *user_data); +

      cups_job_t

      Job

      @@ -2062,7 +1970,7 @@ typedef struct cups_option_s cups_option_t;

      cups_password_cb_t

      Password callback

      -typedef const char *(*cups_password_cb_t)(const char *); +typedef const char *(*cups_password_cb_t)(const char *prompt);

      cups_ptype_t

      Printer type/capability bits

      diff --git a/doc/help/api-httpipp.html b/doc/help/api-httpipp.html index 04fc4a06b..045523702 100644 --- a/doc/help/api-httpipp.html +++ b/doc/help/api-httpipp.html @@ -304,7 +304,12 @@ div.contents ul.subcontents li {
    • cupsDoRequest
    • cupsEncodeOptions
    • cupsEncodeOptions2
    • +
    • cupsGetDevices
    • +
    • cupsGetFd
    • +
    • cupsGetFile
    • cupsGetResponse
    • +
    • cupsPutFd
    • +
    • cupsPutFile
    • cupsReadResponseData
    • cupsSendRequest
    • cupsWriteRequestData
    • @@ -954,6 +959,84 @@ void cupsEncodeOptions2 (
      function multiple times for each group, or use cupsEncodeOptions() to add the standard groups. +

      +

       CUPS 1.4 cupsGetDevices

      +

      Get available printer devices.

      +

      +ipp_status_t cupsGetDevices (
      +    http_t *http,
      +    int timeout,
      +    const char *exclude_schemes,
      +    cups_device_cb_t callback,
      +    void *user_data
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server or CUPS_HTTP_DEFAULT
      +
      timeout
      +
      Timeout in seconds or CUPS_TIMEOUT_DEFAULT
      +
      exclude_schemes
      +
      Comma-separated URI schemes to exclude or CUPS_EXCLUDE_NONE
      +
      callback
      +
      Callback function
      +
      user_data
      +
      User data pointer
      +
      +

      Return Value

      +

      Request status - IPP_OK on success.

      +

      Discussion

      +

      This function sends a CUPS-Get-Devices request and streams the discovered +devices to the specified callback function. The "timeout" parameter controls +how long the request lasts, while the "exclude_schemes" parameter provides +a comma-delimited list of backends to omit from the request. + +

      +

       CUPS 1.1.20 cupsGetFd

      +

      Get a file from the server.

      +

      +http_status_t cupsGetFd (
      +    http_t *http,
      +    const char *resource,
      +    int fd
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server or CUPS_HTTP_DEFAULT
      +
      resource
      +
      Resource name
      +
      fd
      +
      File descriptor
      +
      +

      Return Value

      +

      HTTP status

      +

      Discussion

      +

      This function returns HTTP_OK when the file is successfully retrieved. + +

      +

       CUPS 1.1.20 cupsGetFile

      +

      Get a file from the server.

      +

      +http_status_t cupsGetFile (
      +    http_t *http,
      +    const char *resource,
      +    const char *filename
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server or CUPS_HTTP_DEFAULT
      +
      resource
      +
      Resource name
      +
      filename
      +
      Filename
      +
      +

      Return Value

      +

      HTTP status

      +

      Discussion

      +

      This function returns HTTP_OK when the file is successfully retrieved. +

       CUPS 1.4 cupsGetResponse

      Get a response to an IPP request.

      @@ -976,6 +1059,54 @@ to add the standard groups. cupsSendDocument() or cupsSendRequest(). For requests that return additional data, use httpRead() after getting a successful response. +

      +

       CUPS 1.1.20 cupsPutFd

      +

      Put a file on the server.

      +

      +http_status_t cupsPutFd (
      +    http_t *http,
      +    const char *resource,
      +    int fd
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server or CUPS_HTTP_DEFAULT
      +
      resource
      +
      Resource name
      +
      fd
      +
      File descriptor
      +
      +

      Return Value

      +

      HTTP status

      +

      Discussion

      +

      This function returns HTTP_CREATED when the file is stored +successfully. + +

      +

       CUPS 1.1.20 cupsPutFile

      +

      Put a file on the server.

      +

      +http_status_t cupsPutFile (
      +    http_t *http,
      +    const char *resource,
      +    const char *filename
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server or CUPS_HTTP_DEFAULT
      +
      resource
      +
      Resource name
      +
      filename
      +
      Filename
      +
      +

      Return Value

      +

      HTTP status

      +

      Discussion

      +

      This function returns HTTP_CREATED when the file is stored +successfully. +

       CUPS 1.4 cupsReadResponseData

      Read additional data after the IPP response.

      @@ -1019,7 +1150,7 @@ http_status_t cupsSendRequest (
      resource
      Resource path
      length
      -
      Length of data to follow or CUPS_LENGTH_VARIABLE
      +
      Length of data to follow or CUPS_LENGTH_VARIABLE

      Return Value

      Initial HTTP status

      diff --git a/doc/help/spec-ipp.html b/doc/help/spec-ipp.html index 0d768c9fb..e5d0f3762 100644 --- a/doc/help/spec-ipp.html +++ b/doc/help/spec-ipp.html @@ -1571,6 +1571,12 @@ CUPS-Get-Devices request:
      The client OPTIONALLY supplies a device class keyword to select which devices are returned. +
      "exclude-schemes" (1setOf name) :CUPS 1.4 + +
      The client OPTIONALLY supplies a set of scheme names that the + requestor does not want to discover. If the client omits this attribute, + the server responds with devices of all schemes. +
      "limit" (integer (1:MAX)):
      The client OPTIONALLY supplies this attribute limiting the number of @@ -1583,6 +1589,11 @@ CUPS-Get-Devices request: the client omits this attribute, the server responds as if this attribute had been supplied with a value of 'all'. +
      "timeout" (integer (1:MAX)) :CUPS 1.4 + +
      The client OPTIONALLY supplies this attribute limiting the number of + devices that are returned. +

      CUPS-Get-Devices Response

      diff --git a/filter/error.c b/filter/error.c index f4e8c3983..44c2eabfb 100644 --- a/filter/error.c +++ b/filter/error.c @@ -3,7 +3,7 @@ * * Raster error handling for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -196,8 +196,7 @@ get_error_buffer(void) * Initialize the global data exactly once... */ - DEBUG_printf(("get_error_buffer(): raster_key_once=%d\n", - raster_key_once)); + DEBUG_puts("get_error_buffer()"); pthread_once(&raster_key_once, raster_init); @@ -237,8 +236,8 @@ raster_init(void) { pthread_key_create(&raster_key, raster_destructor); - DEBUG_printf(("raster_init(): raster_key=%x(%u)\n", raster_key, - raster_key)); + DEBUG_printf(("raster_init(): raster_key=%x(%u)\n", (unsigned)raster_key, + (unsigned)raster_key)); } diff --git a/filter/interpret.c b/filter/interpret.c index 0cc782f9c..945c8f40a 100644 --- a/filter/interpret.c +++ b/filter/interpret.c @@ -468,9 +468,8 @@ _cupsRasterExecPS( while ((obj = scan_ps(st, &codeptr)) != NULL) { #ifdef DEBUG - printf(" (%d): ", st->num_objs); + DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)\n", st->num_objs)); DEBUG_object(obj); - putchar('\n'); #endif /* DEBUG */ switch (obj->type) @@ -486,7 +485,7 @@ _cupsRasterExecPS( _cupsRasterAddError("cleartomark: Stack underflow!\n"); #ifdef DEBUG - fputs(" dup: ", stdout); + DEBUG_puts(" dup: "); DEBUG_stack(st); #endif /* DEBUG */ break; @@ -498,7 +497,7 @@ _cupsRasterExecPS( copy_stack(st, (int)obj->value.number); #ifdef DEBUG - fputs(" copy: ", stdout); + DEBUG_puts("_cupsRasterExecPS: copy"); DEBUG_stack(st); #endif /* DEBUG */ } @@ -509,7 +508,7 @@ _cupsRasterExecPS( copy_stack(st, 1); #ifdef DEBUG - fputs(" dup: ", stdout); + DEBUG_puts("_cupsRasterExecPS: dup"); DEBUG_stack(st); #endif /* DEBUG */ break; @@ -521,7 +520,7 @@ _cupsRasterExecPS( index_stack(st, (int)obj->value.number); #ifdef DEBUG - fputs(" index: ", stdout); + DEBUG_puts("_cupsRasterExecPS: index"); DEBUG_stack(st); #endif /* DEBUG */ } @@ -532,7 +531,7 @@ _cupsRasterExecPS( pop_stack(st); #ifdef DEBUG - fputs(" pop: ", stdout); + DEBUG_puts("_cupsRasterExecPS: pop"); DEBUG_stack(st); #endif /* DEBUG */ break; @@ -551,7 +550,7 @@ _cupsRasterExecPS( roll_stack(st, (int)obj->value.number, c); #ifdef DEBUG - fputs(" roll:", stdout); + DEBUG_puts("_cupsRasterExecPS: roll"); DEBUG_stack(st); #endif /* DEBUG */ } @@ -563,7 +562,7 @@ _cupsRasterExecPS( setpagedevice(st, h, preferred_bits); #ifdef DEBUG - fputs(" setpagedevice: ", stdout); + DEBUG_puts("_cupsRasterExecPS: setpagedevice"); DEBUG_stack(st); #endif /* DEBUG */ break; @@ -576,7 +575,8 @@ _cupsRasterExecPS( case CUPS_PS_OTHER : _cupsRasterAddError("Unknown operator \"%s\"!\n", obj->value.other); - DEBUG_printf((" Unknown operator \"%s\"!\n", obj->value.other)); + DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\"!\n", + obj->value.other)); break; } @@ -595,7 +595,7 @@ _cupsRasterExecPS( error_stack(st, "Stack not empty:"); #ifdef DEBUG - fputs(" Stack not empty:", stdout); + DEBUG_puts("_cupsRasterExecPS: Stack not empty:"); DEBUG_stack(st); #endif /* DEBUG */ @@ -1353,7 +1353,7 @@ setpagedevice( * Now pull /name and value pairs from the dictionary... */ - DEBUG_puts(" Dictionary:"); + DEBUG_puts("setpagedevice: Dictionary:"); for (obj ++; obj < end; obj ++) { @@ -1368,9 +1368,8 @@ setpagedevice( obj ++; #ifdef DEBUG - printf(" /%s ", name); + DEBUG_printf(("setpagedevice: /%s ", name)); DEBUG_object(obj); - putchar('\n'); #endif /* DEBUG */ /* @@ -1542,86 +1541,86 @@ DEBUG_object(_cups_ps_obj_t *obj) /* I - Object to print */ switch (obj->type) { case CUPS_PS_NAME : - printf("/%s", obj->value.name); + DEBUG_printf(("/%s\n", obj->value.name)); break; case CUPS_PS_NUMBER : - printf("%g", obj->value.number); + DEBUG_printf(("%g\n", obj->value.number)); break; case CUPS_PS_STRING : - printf("(%s)", obj->value.string); + DEBUG_printf(("(%s)\n", obj->value.string)); break; case CUPS_PS_BOOLEAN : if (obj->value.boolean) - fputs("true", stdout); + DEBUG_puts("true"); else - fputs("false", stdout); + DEBUG_puts("false"); break; case CUPS_PS_NULL : - fputs("null", stdout); + DEBUG_puts("null"); break; case CUPS_PS_START_ARRAY : - fputs("[", stdout); + DEBUG_puts("["); break; case CUPS_PS_END_ARRAY : - fputs("]", stdout); + DEBUG_puts("]"); break; case CUPS_PS_START_DICT : - fputs("<<", stdout); + DEBUG_puts("<<"); break; case CUPS_PS_END_DICT : - fputs(">>", stdout); + DEBUG_puts(">>"); break; case CUPS_PS_START_PROC : - fputs("{", stdout); + DEBUG_puts("{"); break; case CUPS_PS_END_PROC : - fputs("}", stdout); + DEBUG_puts("}"); break; case CUPS_PS_CLEARTOMARK : - fputs("--cleartomark--", stdout); + DEBUG_puts("--cleartomark--"); break; case CUPS_PS_COPY : - fputs("--copy--", stdout); + DEBUG_puts("--copy--"); break; case CUPS_PS_DUP : - fputs("--dup--", stdout); + DEBUG_puts("--dup--"); break; case CUPS_PS_INDEX : - fputs("--index--", stdout); + DEBUG_puts("--index--"); break; case CUPS_PS_POP : - fputs("--pop--", stdout); + DEBUG_puts("--pop--"); break; case CUPS_PS_ROLL : - fputs("--roll--", stdout); + DEBUG_puts("--roll--"); break; case CUPS_PS_SETPAGEDEVICE : - fputs("--setpagedevice--", stdout); + DEBUG_puts("--setpagedevice--"); break; case CUPS_PS_STOPPED : - fputs("--stopped--", stdout); + DEBUG_puts("--stopped--"); break; case CUPS_PS_OTHER : - printf("--%s--", obj->value.other); + DEBUG_printf(("--%s--\n", obj->value.other)); break; } } @@ -1639,12 +1638,7 @@ DEBUG_stack(_cups_ps_stack_t *st) /* I - Stack */ for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++) - { - putchar(' '); DEBUG_object(obj); - } - - putchar('\n'); } #endif /* DEBUG */ diff --git a/filter/pdftops.c b/filter/pdftops.c index f1abb52bf..0529dd144 100644 --- a/filter/pdftops.c +++ b/filter/pdftops.c @@ -68,9 +68,13 @@ main(int argc, /* I - Number of command-line args */ pdfwaitpid, /* Process ID from wait() */ pdfstatus, /* Status from pdftops */ pdfargc; /* Number of args for pdftops */ - char *pdfargv[100], /* Arguments for pdftops */ + char *pdfargv[100], /* Arguments for pdftops/gs */ +#ifdef HAVE_PDFTOPS pdfwidth[255], /* Paper width */ pdfheight[255]; /* Paper height */ +#else + pdfgeometry[255]; /* Paper width and height */ +#endif /* HAVE_PDFTOPS */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ @@ -157,11 +161,22 @@ main(int argc, /* I - Number of command-line args */ cupsMarkOptions(ppd, num_options, options); /* - * Build the command-line for the pdftops filter... + * Build the command-line for the pdftops or gs filter... */ +#ifdef HAVE_PDFTOPS pdfargv[0] = (char *)"pdftops"; pdfargc = 1; +#else + pdfargv[0] = (char *)"gs"; + pdfargv[1] = (char *)"-q"; + pdfargv[2] = (char *)"-dNOPAUSE"; + pdfargv[3] = (char *)"-dBATCH"; + pdfargv[4] = (char *)"-dSAFER"; + pdfargv[5] = (char *)"-sDEVICE=pswrite"; + pdfargv[6] = (char *)"-sOUTPUTFILE=%stdout"; + pdfargc = 7; +#endif /* HAVE_PDFTOPS */ if (ppd) { @@ -171,17 +186,29 @@ main(int argc, /* I - Number of command-line args */ if (ppd->language_level == 1) { +#ifdef HAVE_PDFTOPS pdfargv[pdfargc++] = (char *)"-level1"; pdfargv[pdfargc++] = (char *)"-noembtt"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=1"; +#endif /* HAVE_PDFTOPS */ } else if (ppd->language_level == 2) { +#ifdef HAVE_PDFTOPS pdfargv[pdfargc++] = (char *)"-level2"; if (!ppd->ttrasterizer) pdfargv[pdfargc++] = (char *)"-noembtt"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=2"; +#endif /* HAVE_PDFTOPS */ } else +#ifdef HAVE_PDFTOPS pdfargv[pdfargc++] = (char *)"-level3"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=3"; +#endif /* HAVE_PDFTOPS */ /* * Set output page size... @@ -218,6 +245,7 @@ main(int argc, /* I - Number of command-line args */ orientation ^= 1; } +#ifdef HAVE_PDFTOPS if (orientation & 1) { snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->length); @@ -233,9 +261,20 @@ main(int argc, /* I - Number of command-line args */ pdfargv[pdfargc++] = pdfwidth; pdfargv[pdfargc++] = (char *)"-paperh"; pdfargv[pdfargc++] = pdfheight; +#else + if (orientation & 1) + snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->length, + size->width); + else + snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->width, + size->length); + + pdfargv[pdfargc++] = pdfgeometry; +#endif /* HAVE_PDFTOPS */ } } +#ifdef HAVE_PDFTOPS if ((val = cupsGetOption("fitplot", num_options, options)) != NULL && strcasecmp(val, "no") && strcasecmp(val, "off") && strcasecmp(val, "false")) @@ -243,7 +282,14 @@ main(int argc, /* I - Number of command-line args */ pdfargv[pdfargc++] = filename; pdfargv[pdfargc++] = (char *)"-"; - pdfargv[pdfargc] = NULL; +#else + pdfargv[pdfargc++] = (char *)"-c"; + pdfargv[pdfargc++] = (char *)"save pop"; + pdfargv[pdfargc++] = (char *)"-f"; + pdfargv[pdfargc++] = filename; +#endif /* HAVE_PDFTOPS */ + + pdfargv[pdfargc] = NULL; if ((pdfpid = fork()) == 0) { @@ -251,8 +297,14 @@ main(int argc, /* I - Number of command-line args */ * Child comes here... */ +#ifdef HAVE_PDFTOPS execv(CUPS_PDFTOPS, pdfargv); - _cupsLangPrintError(_("ERROR: Unable to execute pdftops filter")); + _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); +#else + execv(CUPS_GHOSTSCRIPT, pdfargv); + _cupsLangPrintError(_("ERROR: Unable to execute gs program")); +#endif /* HAVE_PDFTOPS */ + exit(1); } else if (pdfpid < 0) @@ -261,7 +313,12 @@ main(int argc, /* I - Number of command-line args */ * Unable to fork! */ - _cupsLangPrintError(_("ERROR: Unable to execute pdftops filter")); +#ifdef HAVE_PDFTOPS + _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); +#else + _cupsLangPrintError(_("ERROR: Unable to execute gs program")); +#endif /* HAVE_PDFTOPS */ + pdfstatus = 1; } else diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c index 62ecb347b..b528bc06b 100644 --- a/filter/rastertoepson.c +++ b/filter/rastertoepson.c @@ -322,11 +322,6 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ void EndPage(const cups_page_header2_t *header) /* I - Page header */ { -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ - - if (DotBytes && header) { /* diff --git a/filter/rastertolabel.c b/filter/rastertolabel.c index cb62278fd..956ae88ab 100644 --- a/filter/rastertolabel.c +++ b/filter/rastertolabel.c @@ -482,9 +482,6 @@ EndPage(ppd_file_t *ppd, /* I - PPD file */ { int val; /* Option value */ ppd_choice_t *choice; /* Marked choice */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ switch (ModelNumber) diff --git a/notifier/mailto.c b/notifier/mailto.c index a83409e95..3376065fe 100644 --- a/notifier/mailto.c +++ b/notifier/mailto.c @@ -3,7 +3,7 @@ * * "mailto" notifier for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -315,7 +315,7 @@ email_message(const char *to, /* I - Recipient of message */ cupsFilePrintf(fp, "Content-Type: text/plain%s", nl); cupsFilePuts(fp, nl); cupsFilePrintf(fp, "%s%s", text, nl); - cupsFilePrintf(fp, ".\n", nl); + cupsFilePrintf(fp, ".%s", nl); /* * Close the connection to the mail server... diff --git a/notifier/rss.c b/notifier/rss.c index c5767a6b1..03f1199bb 100644 --- a/notifier/rss.c +++ b/notifier/rss.c @@ -579,6 +579,7 @@ save_rss(cups_array_t *rss, /* I - RSS messages */ FILE *fp; /* File pointer */ _cups_rss_t *msg; /* Current message */ char date[1024]; /* Current date */ + char *href; /* Escaped base URL */ if ((fp = fopen(filename, "w")) == NULL) @@ -592,7 +593,11 @@ save_rss(cups_array_t *rss, /* I - RSS messages */ fputs("\n", fp); fputs(" \n", fp); fputs(" CUPS RSS Feed\n", fp); - fprintf(fp, " %s\n", baseurl); + + href = xml_escape(baseurl); + fprintf(fp, " %s\n", href); + free(href); + fputs(" CUPS RSS Feed\n", fp); fputs(" " CUPS_SVERSION "\n", fp); fputs(" 1\n", fp); diff --git a/ppdc/ppdc-catalog.cxx b/ppdc/ppdc-catalog.cxx index 29de91f67..db9528e6d 100644 --- a/ppdc/ppdc-catalog.cxx +++ b/ppdc/ppdc-catalog.cxx @@ -178,7 +178,7 @@ ppdcCatalog::load_messages( if ((fp = cupsFileOpen(f, "r")) == NULL) return (-1); - if ((ptr = strrchr(f, '.')) == NULL) + if ((ptr = (char *)strrchr(f, '.')) == NULL) goto unknown_load_format; else if (!strcmp(ptr, ".strings")) { @@ -305,7 +305,7 @@ ppdcCatalog::load_messages( continue; // Strip the trailing quote... - if ((ptr = strrchr(line, '\"')) == NULL) + if ((ptr = (char *)strrchr(line, '\"')) == NULL) { fprintf(stderr, "ERROR: Expected quoted string on line %d of %s!\n", linenum, f); @@ -451,7 +451,7 @@ ppdcCatalog::save_messages( // Open the file... - if ((ptr = strrchr(f, '.')) == NULL) + if ((ptr = (char *)strrchr(f, '.')) == NULL) return (-1); if (!strcmp(ptr, ".gz")) diff --git a/scheduler/client.c b/scheduler/client.c index 94ddc900a..ba016434a 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -2606,7 +2606,8 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdWriteClient(con=%p) %d response=%p(%d), file=%d " "pipe_pid=%d state=%d", - con, con->http.fd, con->response, con->response->state, + con, con->http.fd, con->response, + con->response ? con->response->state : -1, con->file, con->pipe_pid, con->http.state); #endif /* DEBUG */ @@ -2768,6 +2769,8 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ return; } + httpFlushWrite(HTTP(con)); + con->bytes += bytes; if (con->http.state == HTTP_WAITING) diff --git a/scheduler/conf.c b/scheduler/conf.c index 254755648..c8e814886 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -416,7 +416,7 @@ cupsdReadConfiguration(void) cupsdSetString(&PrintcapGUI, "/usr/bin/glpoptions"); cupsdSetString(&FontPath, CUPS_FONTPATH); cupsdSetString(&RemoteRoot, "remroot"); - cupsdSetString(&ServerHeader, "CUPS/1.2"); + cupsdSetString(&ServerHeader, "CUPS/1.4"); cupsdSetString(&StateDir, CUPS_STATEDIR); #ifdef HAVE_GSSAPI cupsdSetString(&GSSServiceName, CUPS_DEFAULT_GSSSERVICENAME); @@ -783,10 +783,14 @@ cupsdReadConfiguration(void) * writable by the user and group in the cupsd.conf file... */ + snprintf(temp, sizeof(temp), "%s/rss", CacheDir); + if (cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1) < 0 || cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser, Group, 1, 1) < 0 || + cupsdCheckPermissions(temp, NULL, 0775, RunUser, + Group, 1, 1) < 0 || cupsdCheckPermissions(StateDir, NULL, 0755, RunUser, Group, 1, 1) < 0 || cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User, @@ -2965,7 +2969,7 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ else if (!strcasecmp(value, "Major")) cupsdSetString(&ServerHeader, "CUPS/1"); else if (!strcasecmp(value, "Minor")) - cupsdSetString(&ServerHeader, "CUPS/1.2"); + cupsdSetString(&ServerHeader, "CUPS/1.4"); else if (!strcasecmp(value, "Minimal")) cupsdSetString(&ServerHeader, CUPS_MINIMAL); else if (!strcasecmp(value, "OS")) diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 385037ea2..9c5b6991f 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -14,11 +14,15 @@ * * Contents: * - * main() - Scan for devices and return an IPP response. - * add_dev() - Add a new device to the list. - * compare_devs() - Compare device names for sorting. - * run_backend() - Run a backend to gather the available devices. - * sigalrm_handler() - Handle alarm signals for backends that get hung + * main() - Scan for devices and return an IPP response. + * add_device() - Add a new device to the list. + * compare_devices() - Compare device names to eliminate duplicates. + * create_strings_array() - Create a CUPS array of strings. + * get_current_time() - Get the current time as a double value in seconds. + * get_device() - Get a device from a backend. + * process_children() - Process all dead children... + * sigchld_handler() - Handle 'child' signals from old processes. + * start_backend() - Run a backend to gather the available devices. */ /* @@ -29,6 +33,29 @@ #include #include #include +#include +#include + + +/* + * Constants... + */ + +#define MAX_BACKENDS 200 /* Maximum number of backends we'll run */ + + +/* + * Backend information... + */ + +typedef struct +{ + char *name; /* Name of backend */ + int pid, /* Process ID */ + status; /* Exit status */ + cups_file_t *pipe; /* Pipe from backend stdout */ + int count; /* Number of devices found */ +} cupsd_backend_t; /* @@ -42,30 +69,51 @@ typedef struct device_info[128], /* Device info/description */ device_uri[1024], /* Device URI */ device_id[1024]; /* 1284 Device ID */ -} dev_info_t; +} cupsd_device_t; /* * Local globals... */ -static int alarm_tripped; /* Non-zero if alarm was tripped */ -static cups_array_t *devs; /* Device info */ +static int num_backends = 0, + /* Total backends */ + active_backends = 0; + /* Active backends */ +static cupsd_backend_t backends[MAX_BACKENDS]; + /* Array of backends */ +static struct pollfd backend_fds[MAX_BACKENDS]; + /* Array for poll() */ +static cups_array_t *devices; /* Array of devices */ static int normal_user; /* Normal user ID */ +static int device_limit; /* Maximum number of devices */ +static int send_class, /* Send device-class attribute? */ + send_info, /* Send device-info attribute? */ + send_make_and_model, + /* Send device-make-and-model attribute? */ + send_uri, /* Send device-uri attribute? */ + send_id; /* Send device-id attribute? */ +static int dead_children = 0; + /* Dead children? */ /* * Local functions... */ -static dev_info_t *add_dev(const char *device_class, - const char *device_make_and_model, - const char *device_info, - const char *device_uri, - const char *device_id); -static int compare_devs(dev_info_t *p0, dev_info_t *p1); -static FILE *run_backend(const char *backend, int uid, int *pid); -static void sigalrm_handler(int sig); +static int add_device(const char *device_class, + const char *device_make_and_model, + const char *device_info, + const char *device_uri, + const char *device_id); +static int compare_devices(cupsd_device_t *p0, + cupsd_device_t *p1); +static cups_array_t *create_strings_array(const char *s); +static double get_current_time(void); +static int get_device(cupsd_backend_t *backend); +static void process_children(void); +static void sigchld_handler(int sig); +static int start_backend(const char *backend, int root); /* @@ -80,31 +128,19 @@ int /* O - Exit code */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { - const char *server_bin; /* CUPS_SERVERBIN environment variable */ - char backends[1024]; /* Location of backends */ + int i; /* Looping var */ int request_id; /* Request ID */ - int count; /* Number of devices from backend */ - int compat; /* Compatibility device? */ - FILE *fp; /* Pipe to device backend */ - int pid; /* Process ID of backend */ + int timeout; /* Timeout in seconds */ + const char *server_bin; /* CUPS_SERVERBIN environment variable */ + char filename[1024]; /* Backend directory filename */ cups_dir_t *dir; /* Directory pointer */ cups_dentry_t *dent; /* Directory entry */ - char filename[1024], /* Name of backend */ - line[2048], /* Line from backend */ - dclass[64], /* Device class */ - uri[1024], /* Device URI */ - info[128], /* Device info */ - make_model[256], /* Make and model */ - device_id[1024]; /* 1284 device ID */ + double current_time, /* Current time */ + end_time; /* Ending time */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ - const char *requested; /* requested-attributes option */ - int send_class, /* Send device-class attribute? */ - send_info, /* Send device-info attribute? */ - send_make_and_model, /* Send device-make-and-model attribute? */ - send_uri, /* Send device-uri attribute? */ - send_id; /* Send device-id attribute? */ - dev_info_t *dev; /* Current device */ + cups_array_t *requested, /* requested-attributes values */ + *exclude; /* exclude-schemes values */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ @@ -116,53 +152,79 @@ main(int argc, /* I - Number of command-line args */ * Check the command-line... */ - if (argc > 1) - request_id = atoi(argv[1]); - else - request_id = 1; - - if (argc != 5) + if (argc != 6) { - fputs("Usage: cups-deviced request-id limit user-id options\n", stderr); + fputs("Usage: cups-deviced request-id limit timeout user-id options\n", stderr); return (1); } + request_id = atoi(argv[1]); if (request_id < 1) { - fprintf(stderr, "cups-deviced: Bad request ID %d!\n", request_id); + fprintf(stderr, "ERROR: [cups-deviced] Bad request ID %d!\n", request_id); return (1); } - normal_user = atoi(argv[3]); - if (normal_user <= 0) + device_limit = atoi(argv[2]); + if (device_limit < 0) { - fprintf(stderr, "cups-deviced: Bad user %d!\n", normal_user); + fprintf(stderr, "ERROR: [cups-deviced] Bad limit %d!\n", device_limit); return (1); } - num_options = cupsParseOptions(argv[4], 0, &options); - requested = cupsGetOption("requested-attributes", num_options, options); + timeout = atoi(argv[3]); + if (timeout < 1) + { + fprintf(stderr, "ERROR: [cups-deviced] Bad timeout %d!\n", timeout); + + return (1); + } - if (!requested || strstr(requested, "all")) + normal_user = atoi(argv[4]); + if (normal_user <= 0) { - send_class = 1; - send_info = 1; - send_make_and_model = 1; - send_uri = 1; - send_id = 1; + fprintf(stderr, "ERROR: [cups-deviced] Bad user %d!\n", normal_user); + + return (1); } + + num_options = cupsParseOptions(argv[5], 0, &options); + requested = create_strings_array(cupsGetOption("requested-attributes", + num_options, options)); + exclude = create_strings_array(cupsGetOption("exclude-schemes", + num_options, options)); + + if (!requested || cupsArrayFind(requested, "all") != NULL) + send_class = send_info = send_make_and_model = send_uri = send_id = 1; else { - send_class = strstr(requested, "device-class") != NULL; - send_info = strstr(requested, "device-info") != NULL; - send_make_and_model = strstr(requested, "device-make-and-model") != NULL; - send_uri = strstr(requested, "device-uri") != NULL; - send_id = strstr(requested, "device-id") != NULL; + send_class = cupsArrayFind(requested, "device-class") != NULL; + send_info = cupsArrayFind(requested, "device-info") != NULL; + send_make_and_model = cupsArrayFind(requested, "device-make-and-model") != NULL; + send_uri = cupsArrayFind(requested, "device-uri") != NULL; + send_id = cupsArrayFind(requested, "device-id") != NULL; } + /* + * Listen to child signals... + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGCHLD, sigchld_handler); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGCHLD); + action.sa_handler = sigchld_handler; + sigaction(SIGCHLD, &action, NULL); +#else + signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */ +#endif /* HAVE_SIGSET */ + /* * Try opening the backend directory... */ @@ -170,12 +232,12 @@ main(int argc, /* I - Number of command-line args */ if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL) server_bin = CUPS_SERVERBIN; - snprintf(backends, sizeof(backends), "%s/backend", server_bin); + snprintf(filename, sizeof(filename), "%s/backend", server_bin); - if ((dir = cupsDirOpen(backends)) == NULL) + if ((dir = cupsDirOpen(filename)) == NULL) { fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory " - "\"%s\": %s", backends, strerror(errno)); + "\"%s\": %s", filename, strerror(errno)); return (1); } @@ -184,7 +246,7 @@ main(int argc, /* I - Number of command-line args */ * Setup the devices array... */ - devs = cupsArrayNew((cups_array_func_t)compare_devs, NULL); + devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL); /* * Loop through all of the device backends... @@ -197,273 +259,172 @@ main(int argc, /* I - Number of command-line args */ */ if (!S_ISREG(dent->fileinfo.st_mode) || + !isalnum(dent->filename[0] & 255) || (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR)) continue; - /* - * Change effective users depending on the backend permissions... - */ - - snprintf(filename, sizeof(filename), "%s/%s", backends, dent->filename); + if (cupsArrayFind(exclude, dent->filename)) + continue; /* * Backends without permissions for normal users run as root, * all others run as the unprivileged user... */ - fp = run_backend(filename, - (dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO)) - ? normal_user : 0, - &pid); - - /* - * Collect the output from the backend... - */ - - if (fp) - { - /* - * Set an alarm for the first read from the backend; this avoids - * problems when a backend is hung getting device information. - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGALRM, sigalrm_handler); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - sigaddset(&action.sa_mask, SIGALRM); - action.sa_handler = sigalrm_handler; - sigaction(SIGALRM, &action, NULL); -#else - signal(SIGALRM, sigalrm_handler); -#endif /* HAVE_SIGSET */ - - alarm_tripped = 0; - count = 0; - compat = !strcmp(dent->filename, "smb"); - - alarm(30); - - while (fgets(line, sizeof(line), fp) != NULL) - { - /* - * Reset the alarm clock... - */ - - alarm(30); - - /* - * Each line is of the form: - * - * class URI "make model" "name" ["1284 device ID"] - */ - - device_id[0] = '\0'; - - if (!strncasecmp(line, "Usage", 5)) - compat = 1; - else if (sscanf(line, - "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%1023[^\"]", - dclass, uri, make_model, info, device_id) < 4) - { - /* - * Bad format; strip trailing newline and write an error message. - */ - - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; - - fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n", - dent->filename, line); - compat = 1; - break; - } - else - { - /* - * Add the device to the array of available devices... - */ - - dev = add_dev(dclass, make_model, info, uri, device_id); - if (!dev) - { - cupsDirClose(dir); - fclose(fp); - kill(pid, SIGTERM); - return (1); - } - - fprintf(stderr, "DEBUG: [cups-deviced] Added device \"%s\"...\n", - uri); - count ++; - } - } - - /* - * Turn the alarm clock off and close the pipe to the command... - */ - - alarm(0); - - if (alarm_tripped) - fprintf(stderr, "WARNING: [cups-deviced] Backend \"%s\" did not " - "respond within 30 seconds!\n", dent->filename); - - fclose(fp); - kill(pid, SIGTERM); - - /* - * Hack for backends that don't support the CUPS 1.1 calling convention: - * add a network device with the method == backend name. - */ - - if (count == 0 && compat) - { - snprintf(line, sizeof(line), "Unknown Network Device (%s)", - dent->filename); - - dev = add_dev("network", line, "Unknown", dent->filename, ""); - if (!dev) - { - cupsDirClose(dir); - return (1); - } - - fprintf(stderr, "DEBUG: [cups-deviced] Compatibility device " - "\"%s\"...\n", dent->filename); - } - } - else - fprintf(stderr, "WARNING: [cups-deviced] Unable to execute \"%s\" " - "backend: %s\n", dent->filename, strerror(errno)); + start_backend(dent->filename, + !(dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO))); } cupsDirClose(dir); /* - * Output the list of devices... + * Collect devices... */ - puts("Content-Type: application/ipp\n"); + if (getenv("SOFTWARE")) + puts("Content-Type: application/ipp\n"); cupsdSendIPPHeader(IPP_OK, request_id); cupsdSendIPPGroup(IPP_TAG_OPERATION); cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); - if ((count = atoi(argv[2])) <= 0) - count = cupsArrayCount(devs); - - if (count > cupsArrayCount(devs)) - count = cupsArrayCount(devs); + end_time = get_current_time() + timeout; - for (dev = (dev_info_t *)cupsArrayFirst(devs); - count > 0; - count --, dev = (dev_info_t *)cupsArrayNext(devs)) + while (active_backends > 0 && (current_time = get_current_time()) < end_time) { /* - * Add strings to attributes... + * Collect the output from the backends... + */ + + timeout = (int)(1000 * (end_time - current_time)); + + if (poll(backend_fds, num_backends, timeout) > 0) + { + for (i = 0; i < num_backends; i ++) + if (backend_fds[i].revents && backends[i].pipe) + if (get_device(backends + i)) + { + backend_fds[i].fd = 0; + backend_fds[i].events = 0; + } + } + + /* + * Get exit status from children... */ - cupsdSendIPPGroup(IPP_TAG_PRINTER); - if (send_class) - cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class", dev->device_class); - if (send_info) - cupsdSendIPPString(IPP_TAG_TEXT, "device-info", dev->device_info); - if (send_make_and_model) - cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model", - dev->device_make_and_model); - if (send_uri) - cupsdSendIPPString(IPP_TAG_URI, "device-uri", dev->device_uri); - if (send_id) - cupsdSendIPPString(IPP_TAG_TEXT, "device-id", dev->device_id); + if (dead_children) + process_children(); } cupsdSendIPPTrailer(); /* - * Free the devices array and return... + * Terminate any remaining backends and exit... */ - for (dev = (dev_info_t *)cupsArrayFirst(devs); - dev; - dev = (dev_info_t *)cupsArrayNext(devs)) - free(dev); - - cupsArrayDelete(devs); + if (active_backends > 0) + { + for (i = 0; i < num_backends; i ++) + if (backends[i].pid) + kill(backends[i].pid, SIGTERM); + } return (0); } /* - * 'add_dev()' - Add a new device to the list. + * 'add_device()' - Add a new device to the list. */ -static dev_info_t * /* O - New device or NULL on error */ -add_dev( +static int /* O - 0 on success, -1 on error */ +add_device( const char *device_class, /* I - Device class */ const char *device_make_and_model, /* I - Device make and model */ const char *device_info, /* I - Device information */ const char *device_uri, /* I - Device URI */ const char *device_id) /* I - 1284 device ID */ { - dev_info_t *dev, /* New device */ - *temp; /* Found device */ + cupsd_device_t *device, /* New device */ + *temp; /* Found device */ /* * Allocate memory for the device record... */ - if ((dev = calloc(1, sizeof(dev_info_t))) == NULL) + if ((device = calloc(1, sizeof(cupsd_device_t))) == NULL) { fputs("ERROR: [cups-deviced] Ran out of memory allocating a device!\n", stderr); - return (NULL); + return (-1); } /* * Copy the strings over... */ - strlcpy(dev->device_class, device_class, sizeof(dev->device_class)); - strlcpy(dev->device_make_and_model, device_make_and_model, - sizeof(dev->device_make_and_model)); - strlcpy(dev->device_info, device_info, sizeof(dev->device_info)); - strlcpy(dev->device_uri, device_uri, sizeof(dev->device_uri)); - strlcpy(dev->device_id, device_id, sizeof(dev->device_id)); + strlcpy(device->device_class, device_class, sizeof(device->device_class)); + strlcpy(device->device_make_and_model, device_make_and_model, + sizeof(device->device_make_and_model)); + strlcpy(device->device_info, device_info, sizeof(device->device_info)); + strlcpy(device->device_uri, device_uri, sizeof(device->device_uri)); + strlcpy(device->device_id, device_id, sizeof(device->device_id)); /* * Add the device to the array and return... */ - if ((temp = cupsArrayFind(devs, dev)) != NULL) + if ((temp = cupsArrayFind(devices, device)) != NULL) { /* * Avoid duplicates! */ - free(dev); - dev = temp; + free(device); } else - cupsArrayAdd(devs, dev); - - return (dev); + { + cupsArrayAdd(devices, device); + + if (device_limit <= 0 || cupsArrayCount(devices) < device_limit) + { + /* + * Send device info... + */ + + cupsdSendIPPGroup(IPP_TAG_PRINTER); + if (send_class) + cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class", + device->device_class); + if (send_info) + cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device->device_info); + if (send_make_and_model) + cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model", + device->device_make_and_model); + if (send_uri) + cupsdSendIPPString(IPP_TAG_URI, "device-uri", device->device_uri); + if (send_id) + cupsdSendIPPString(IPP_TAG_TEXT, "device-id", device->device_id); + + fflush(stdout); + fputs("DEBUG: Flushed attributes...\n", stderr); + } + } + + return (0); } /* - * 'compare_devs()' - Compare device names for sorting. + * 'compare_devices()' - Compare device names to eliminate duplicates. */ static int /* O - Result of comparison */ -compare_devs(dev_info_t *d0, /* I - First device */ - dev_info_t *d1) /* I - Second device */ +compare_devices(cupsd_device_t *d0, /* I - First device */ + cupsd_device_t *d1) /* I - Second device */ { int diff; /* Difference between strings */ @@ -482,44 +443,276 @@ compare_devs(dev_info_t *d0, /* I - First device */ /* - * 'run_backend()' - Run a backend to gather the available devices. + * 'create_strings_array()' - Create a CUPS array of strings. */ -static FILE * /* O - stdout of backend */ -run_backend(const char *backend, /* I - Backend to run */ - int uid, /* I - User ID to run as */ - int *pid) /* O - Process ID of backend */ +static cups_array_t * /* O - CUPS array */ +create_strings_array(const char *s) /* I - Comma-delimited strings */ { - int fds[2]; /* Pipe file descriptors */ + cups_array_t *a; /* CUPS array */ + const char *start, /* Start of string */ + *end; /* End of string */ + char *ptr; /* New string */ + + + if (!s) + return (NULL); + + if ((a = cupsArrayNew((cups_array_func_t)strcmp, NULL)) != NULL) + { + for (start = end = s; *end; start = end + 1) + { + /* + * Find the end of the current delimited string... + */ + + if ((end = strchr(start, ',')) == NULL) + end = start + strlen(start); + + /* + * Duplicate the string and add it to the array... + */ + + if ((ptr = calloc(1, end - start + 1)) == NULL) + break; + memcpy(ptr, start, end - start); + cupsArrayAdd(a, ptr); + } + } + + return (a); +} + + +/* + * 'get_current_time()' - Get the current time as a double value in seconds. + */ + +static double /* O - Time in seconds */ +get_current_time(void) +{ + struct timeval curtime; /* Current time */ + + + gettimeofday(&curtime, NULL); + + return (curtime.tv_sec + 0.000001 * curtime.tv_usec); +} + + +/* + * 'get_device()' - Get a device from a backend. + */ + +static int /* O - 0 on success, -1 on error */ +get_device(cupsd_backend_t *backend) /* I - Backend to read from */ +{ + char line[2048], /* Line from backend */ + dclass[64], /* Device class */ + uri[1024], /* Device URI */ + info[128], /* Device info */ + make_model[256], /* Make and model */ + device_id[1024]; /* 1284 device ID */ + + + if (cupsFileGets(backend->pipe, line, sizeof(line))) + { + /* + * Each line is of the form: + * + * class URI "make model" "name" ["1284 device ID"] + */ + + device_id[0] = '\0'; + + if (sscanf(line, + "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%1023[^\"]", + dclass, uri, make_model, info, device_id) < 4) + { + /* + * Bad format; strip trailing newline and write an error message. + */ + + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n", + backend->name, line); + } + else + { + /* + * Add the device to the array of available devices... + */ + + if (!add_device(dclass, make_model, info, uri, device_id)) + fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri); + } + + return (0); + } + + /* + * End of file... + */ + + cupsFileClose(backend->pipe); + backend->pipe = NULL; + + return (-1); +} + + +/* + * 'process_children()' - Process all dead children... + */ + +static void +process_children(void) +{ + int i; /* Looping var */ + int status; /* Exit status of child */ + int pid; /* Process ID of child */ + cupsd_backend_t *backend; /* Current backend */ + const char *name; /* Name of process */ + + + /* + * Reset the dead_children flag... + */ + + dead_children = 0; + + /* + * Collect the exit status of some children... + */ + +#ifdef HAVE_WAITPID + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) +#elif defined(HAVE_WAIT3) + while ((pid = wait3(&status, WNOHANG, NULL)) > 0) +#else + if ((pid = wait(&status)) > 0) +#endif /* HAVE_WAITPID */ + { + if (status == SIGTERM) + status = 0; + + for (i = num_backends, backend = backends; i > 0; i --, backend ++) + if (backend->pid == pid) + break; + + if (i > 0) + { + name = backend->name; + backend->pid = 0; + backend->status = status; + + active_backends --; + } + else + name = "Unknown"; + + if (status) + { + if (WIFEXITED(status)) + fprintf(stderr, + "ERROR: [cups-deviced] PID %d (%s) stopped with status %d!\n", + pid, name, WEXITSTATUS(status)); + else + fprintf(stderr, + "ERROR: [cups-deviced] PID %d (%s) crashed on signal %d!\n", + pid, name, WTERMSIG(status)); + } + else + fprintf(stderr, + "DEBUG: [cups-deviced] PID %d (%s) exited with no errors.\n", + pid, name); + } +} + + +/* + * 'sigchld_handler()' - Handle 'child' signals from old processes. + */ + +static void +sigchld_handler(int sig) /* I - Signal number */ +{ + (void)sig; + + /* + * Flag that we have dead children... + */ + + dead_children = 1; + + /* + * Reset the signal handler as needed... + */ + +#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION) + signal(SIGCLD, sigchld_handler); +#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */ +} + + +/* + * 'start_backend()' - Run a backend to gather the available devices. + */ + +static int /* O - 0 on success, -1 on error */ +start_backend(const char *name, /* I - Backend to run */ + int root) /* I - Run as root? */ +{ + const char *server_bin; /* CUPS_SERVERBIN environment variable */ + char program[1024]; /* Full path to backend */ + int fds[2]; /* Pipe file descriptors */ + cupsd_backend_t *backend; /* Current backend */ + + + if (num_backends >= MAX_BACKENDS) + { + fprintf(stderr, "ERROR: Too many backends (%d)!\n", num_backends); + return (-1); + } if (pipe(fds)) { fprintf(stderr, "ERROR: Unable to create a pipe for \"%s\" - %s\n", - backend, strerror(errno)); - return (NULL); + name, strerror(errno)); + return (-1); } - if ((*pid = fork()) < 0) + if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL) + server_bin = CUPS_SERVERBIN; + + snprintf(program, sizeof(program), "%s/backend/%s", server_bin, name); + + backend = backends + num_backends; + + if ((backend->pid = fork()) < 0) { /* * Error! */ - fprintf(stderr, "ERROR: Unable to fork for \"%s\" - %s\n", backend, - strerror(errno)); + fprintf(stderr, "ERROR: [cups-deviced] Unable to fork for \"%s\" - %s\n", + program, strerror(errno)); close(fds[0]); close(fds[1]); - return (NULL); + return (-1); } - else if (!*pid) + else if (!backend->pid) { /* * Child comes here... */ - if (!getuid() && uid) - setuid(uid); /* Run as restricted user */ + if (!getuid() && !root) + setuid(normal_user); /* Run as restricted user */ close(0); /* pid); - return (fdopen(fds[0], "r")); -} + close(fds[1]); + backend_fds[num_backends].fd = fds[0]; + backend_fds[num_backends].events = POLLIN; -/* - * 'sigalrm_handler()' - Handle alarm signals for backends that get hung - * trying to list the available devices... - */ + backend->name = strdup(name); + backend->status = 0; + backend->pipe = cupsFileOpenFd(fds[0], "r"); + backend->count = 0; -static void -sigalrm_handler(int sig) /* I - Signal number */ -{ - (void)sig; /* remove compiler warnings... */ + active_backends ++; + num_backends ++; - alarm_tripped = 1; + return (0); } diff --git a/scheduler/filter.c b/scheduler/filter.c index 30231306d..73344b6ae 100644 --- a/scheduler/filter.c +++ b/scheduler/filter.c @@ -275,7 +275,7 @@ find_filters(mime_t *mime, /* I - MIME database */ * Got a direct filter! */ - DEBUG_puts("Direct filter found!"); + DEBUG_puts("find_filters: Direct filter found!"); if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL) return (NULL); @@ -287,8 +287,8 @@ find_filters(mime_t *mime, /* I - MIME database */ if (!cost) return (mintemp); - DEBUG_puts(" Found direct filter:"); - DEBUG_printf((" %s (cost=%d)\n", current->filter, mincost)); + DEBUG_puts("find_filters: Found direct filter:"); + DEBUG_printf(("find_filters: %s (cost=%d)\n", current->filter, mincost)); } else { @@ -381,11 +381,13 @@ find_filters(mime_t *mime, /* I - MIME database */ */ #ifdef DEBUG - printf(" Returning %d filters:\n", cupsArrayCount(mintemp)); + DEBUG_printf(("find_filters: Returning %d filters:\n", + cupsArrayCount(mintemp))); + for (current = (mime_filter_t *)cupsArrayFirst(mintemp); current; current = (mime_filter_t *)cupsArrayNext(mintemp)) - printf(" %s\n", current->filter); + DEBUG_printf(("find_filters: %s\n", current->filter)); #endif /* DEBUG */ if (cost) @@ -394,7 +396,7 @@ find_filters(mime_t *mime, /* I - MIME database */ return (mintemp); } - DEBUG_puts(" Returning zippo..."); + DEBUG_puts("find_filters: Returning zippo..."); return (NULL); } diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 9ecca1cde..f29006b86 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -6158,12 +6158,16 @@ static void get_devices(cupsd_client_t *con) /* I - Client connection */ { http_status_t status; /* Policy status */ - ipp_attribute_t *limit, /* Limit attribute */ - *requested; /* requested-attributes attribute */ + ipp_attribute_t *limit, /* limit attribute */ + *timeout, /* timeout attribute */ + *requested, /* requested-attributes attribute */ + *exclude; /* exclude-schemes attribute */ char command[1024], /* cups-deviced command */ options[1024], /* Options to pass to command */ - requested_str[256]; + requested_str[256], /* String for requested attributes */ + exclude_str[512]; + /* String for excluded attributes */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->http.fd); @@ -6182,21 +6186,31 @@ get_devices(cupsd_client_t *con) /* I - Client connection */ * Run cups-deviced command with the given options... */ - limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER); + limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER); + timeout = ippFindAttribute(con->request, "timeout", IPP_TAG_INTEGER); requested = ippFindAttribute(con->request, "requested-attributes", IPP_TAG_KEYWORD); + exclude = ippFindAttribute(con->request, "exclude-schemes", IPP_TAG_NAME); if (requested) url_encode_attr(requested, requested_str, sizeof(requested_str)); else strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str)); + if (exclude) + url_encode_attr(exclude, exclude_str, sizeof(exclude_str)); + else + exclude_str[0] = '\0'; + snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin); snprintf(options, sizeof(options), - "%d+%d+%d+%s", + "%d+%d+%d+%d+%s%s%s", con->request->request.op.request_id, - limit ? limit->values[0].integer : 0, (int)User, - requested_str); + limit ? limit->values[0].integer : 0, + timeout ? timeout->values[0].integer : 10, + (int)User, + requested_str, + exclude_str[0] ? "%20" : "", exclude_str); if (cupsdSendCommand(con, command, options, 1)) { diff --git a/scheduler/main.c b/scheduler/main.c index 8ecd4309e..e831920a0 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -1730,7 +1730,7 @@ process_children(void) */ static void -sigchld_handler(int sig) /* I - Signal number */ +sigchld_handler(int sig) /* I - Signal number */ { (void)sig; @@ -1755,7 +1755,7 @@ sigchld_handler(int sig) /* I - Signal number */ */ static void -sighup_handler(int sig) /* I - Signal number */ +sighup_handler(int sig) /* I - Signal number */ { (void)sig; @@ -1773,7 +1773,7 @@ sighup_handler(int sig) /* I - Signal number */ */ static void -sigterm_handler(int sig) /* I - Signal */ +sigterm_handler(int sig) /* I - Signal number */ { (void)sig; /* remove compiler warnings... */ diff --git a/systemv/lpinfo.c b/systemv/lpinfo.c index b8697c2c8..137304994 100644 --- a/systemv/lpinfo.c +++ b/systemv/lpinfo.c @@ -15,6 +15,7 @@ * Contents: * * main() - Parse options and show information. + * device_cb - Device callback. * show_devices() - Show available devices. * show_models() - Show available PPDs. */ @@ -36,6 +37,10 @@ * Local functions... */ +static void device_cb(const char *device_clas, const char *device_id, + const char *device_info, + const char *device_make_and_model, + const char *device_uri, void *user_data); static int show_devices(http_t *, int); static int show_models(http_t *, int); @@ -158,134 +163,53 @@ main(int argc, /* I - Number of command-line arguments */ /* - * 'show_devices()' - Show available devices. + * 'device_cb()' - Device callback. */ -static int /* O - 0 on success, 1 on failure */ -show_devices(http_t *http, /* I - HTTP connection to server */ - int long_status) /* I - Long status report? */ +static void +device_cb( + const char *device_class, /* I - device-class string */ + const char *device_id, /* I - device-id string */ + const char *device_info, /* I - device-info string */ + const char *device_make_and_model, /* I - device-make-and-model string */ + const char *device_uri, /* I - device-uri string */ + void *user_data) /* I - User data */ { - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - const char *device_class, /* Pointer to device-class */ - *device_id, /* Pointer to device-id */ - *device_info, /* Pointer to device-info */ - *device_make, /* Pointer to device-make-and-model */ - *device_uri; /* Pointer to device-uri */ - + int *long_status; /* Show verbose info? */ - if (http == NULL) - return (1); /* - * Build a CUPS_GET_DEVICES request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language + * Display the device... */ - request = ippNewRequest(CUPS_GET_DEVICES); - - /* - * Do the request and get back a response... - */ + long_status = (int *)user_data; - if ((response = cupsDoRequest(http, request, "/")) != NULL) + if (*long_status) { - /* - * Loop through the device list and display them... - */ - - if (response->request.status.status_code > IPP_OK_CONFLICT) - { - _cupsLangPrintf(stderr, "lpinfo: %s\n", cupsLastErrorString()); - ippDelete(response); - return (1); - } - - for (attr = response->attrs; attr != NULL; attr = attr->next) - { - /* - * Skip leading attributes until we hit a device... - */ - - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (attr == NULL) - break; - - /* - * Pull the needed attributes from this device... - */ - - device_class = NULL; - device_info = NULL; - device_make = NULL; - device_uri = NULL; - device_id = "NONE"; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (!strcmp(attr->name, "device-class") && - attr->value_tag == IPP_TAG_KEYWORD) - device_class = attr->values[0].string.text; - else if (!strcmp(attr->name, "device-info") && - attr->value_tag == IPP_TAG_TEXT) - device_info = attr->values[0].string.text; - else if (!strcmp(attr->name, "device-make-and-model") && - attr->value_tag == IPP_TAG_TEXT) - device_make = attr->values[0].string.text; - else if (!strcmp(attr->name, "device-uri") && - attr->value_tag == IPP_TAG_URI) - device_uri = attr->values[0].string.text; - else if (!strcmp(attr->name, "device-id") && - attr->value_tag == IPP_TAG_TEXT) - device_id = attr->values[0].string.text; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (device_class == NULL || device_info == NULL || - device_make == NULL || device_uri == NULL) - { - if (attr == NULL) - break; - else - continue; - } - - /* - * Display the device... - */ + _cupsLangPrintf(stdout, + _("Device: uri = %s\n" + " class = %s\n" + " info = %s\n" + " make-and-model = %s\n" + " device-id = %s\n"), + device_uri, device_class, device_info, + device_make_and_model, device_id); + } + else + _cupsLangPrintf(stdout, "%s %s\n", device_class, device_uri); +} - if (long_status) - { - _cupsLangPrintf(stdout, - _("Device: uri = %s\n" - " class = %s\n" - " info = %s\n" - " make-and-model = %s\n" - " device-id = %s\n"), - device_uri, device_class, device_info, device_make, - device_id); - } - else - _cupsLangPrintf(stdout, "%s %s\n", device_class, device_uri); - if (attr == NULL) - break; - } +/* + * 'show_devices()' - Show available devices. + */ - ippDelete(response); - } - else +static int /* O - 0 on success, 1 on failure */ +show_devices(http_t *http, /* I - HTTP connection to server */ + int long_status) /* I - Long status report? */ +{ + if (cupsGetDevices(http, CUPS_TIMEOUT_DEFAULT, CUPS_EXCLUDE_NONE, device_cb, + &long_status) != IPP_OK) { _cupsLangPrintf(stderr, "lpinfo: %s\n", cupsLastErrorString()); return (1); -- 2.39.2