]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Import CUPS 1.4svn-r7464.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Thu, 17 Apr 2008 00:50:22 +0000 (00:50 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Thu, 17 Apr 2008 00:50:22 +0000 (00:50 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@713 a1ca3aef-8c08-0410-bb20-df032aa958be

58 files changed:
CHANGES-1.3.txt
CHANGES.txt
backend/Makefile
backend/snmp.c
backend/test1284.c
backend/usb-darwin.c
berkeley/lpq.c
cgi-bin/help-index.c
cgi-bin/var.c
conf/cupsd.conf.in
config-scripts/cups-compiler.m4
config-scripts/cups-defaults.m4
config-scripts/cups-pdf.m4
config.h.in
cups/Makefile
cups/array.c
cups/auth.c
cups/cups.h
cups/debug.c [new file with mode: 0644]
cups/debug.h
cups/dest.c
cups/emit.c
cups/encode.c
cups/file.h
cups/getdevices.c [new file with mode: 0644]
cups/globals.c
cups/globals.h
cups/http-addrlist.c
cups/http.c
cups/ipp-support.c
cups/ipp.c
cups/language.c
cups/libcups.exp
cups/localize.c
cups/mark.c
cups/ppd.c
cups/request.c
cups/string.c
cups/testfile.c
cups/util.c
doc/help/api-cups.html
doc/help/api-httpipp.html
doc/help/spec-ipp.html
filter/error.c
filter/interpret.c
filter/pdftops.c
filter/rastertoepson.c
filter/rastertolabel.c
notifier/mailto.c
notifier/rss.c
ppdc/ppdc-catalog.cxx
scheduler/client.c
scheduler/conf.c
scheduler/cups-deviced.c
scheduler/filter.c
scheduler/ipp.c
scheduler/main.c
systemv/lpinfo.c

index e2b84293ecae89aeb5e75be68b40336c2e2e18a5..271225ac78fddebec09f3183eb680db397e6d091 100644 (file)
@@ -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
index 7c0a2f2b236e2fa83a7367fcb5a147f50ad93c96..de23174da225c918a5e88021c5b7502037a24886 100644 (file)
@@ -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.
index c898b3db0bfeaacf5b1a359999ef57ac99efb4b9..c8af61b381838e730aaffd6ac1613363602af58b 100644 (file)
@@ -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)
 
 
 #
index abfa6215a4dceec8fea837071faca15dbc6f249a..4e0cd1d6f764d40f400d8e0d1584e6f4f4d82409 100644 (file)
@@ -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);
index 62905e2dffd1457808fa601eaf82f6b93fb907bd..bbb4f2c3f46a4eae0afc0db81d81f165119cc766 100644 (file)
@@ -34,7 +34,9 @@
 #  include <fcntl.h>
 #endif /* WIN32 */
 
-#define DEBUG
+#ifndef DEBUG
+#  define DEBUG
+#endif /* !DEBUG */
 #include "ieee1284.c"
 
 
index ab103c24dbe467c3eecde8e089a6d82723878553..f9197173eb54d5601519ed69e8c4b2f324b09079 100644 (file)
@@ -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);
index 18b2e1ccd2f74d26d5aeeb166caaec198d2093e8..7ffb2a8e92f9fd4ccca6bbcf92008f11a7837f03 100644 (file)
@@ -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);
index b32f8a7af3e859a4cdbaab709c393ed963101cd2..64f1380acd9db8f1ff564ebef43cf86e72a50555 100644 (file)
@@ -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;
index 3ae98ca6c7e9fe352ff41d0b244cbdac7271fe39..596b24d0daa8cf58028706aac931f072d938830a 100644 (file)
@@ -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 */
 }
 
index 40917e9b3cd63363614ddf70ec522e7d0e2a1b82..55b7c5ca8b868d21f8219c866cdb72a2fb9c6dd1 100644 (file)
@@ -53,7 +53,7 @@ DefaultAuthType Basic
   </Limit>
 
   # All administration operations require an administrator to authenticate...
-  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
+  <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices>
     AuthType Default
     Require user @SYSTEM
     Order deny,allow
index 1fb08a5201955ef963b5a8895e9e3f693efa7bec..4b1f83c8c8ec77b4a327cd121502387ce1f10e47 100644 (file)
@@ -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
index c09b99a98833e8c99280b01335ad76ce8273689a..b72631f4cda974f8df0405f66e8c48b5e5414b6f 100644 (file)
@@ -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)
index 6e4ed8fb04d954b82740277adbc1be0a1d3cd81b..e980f1de54d0c150c8d1d6c2443e8a4f4575fff1 100644 (file)
@@ -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
index fc9013137363fb9c394f76c831e68362bf516462..5e0c08af1f8bd425c0bd4cd6ac63742112a487da 100644 (file)
@@ -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
  * 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?
  */
index 5e66a122b73261f5e437e36bf9e69801976c0cf0..3ea42068148f497a1d9da3e3696c1ab36b65b10e 100644 (file)
@@ -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" \
index df1ae2e5405574dd5db0e041c5e0b97541238ff2..9d9790bd5c9eb2adba3f6c1d882e7bcd7b00cf1a 100644 (file)
@@ -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");
index 4391a3db04c6b6e4aa08021d8ca7d97ef6aadd98..d3d38b47ed5a64d8cfaba5e82ad34f399b243138 100644 (file)
@@ -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);
 
index fd8cc3aa31f8452e4c24070429a31612986ef644..4321a459e7dbbd039be5bf82a3e5e266153cae67 100644 (file)
@@ -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 (file)
index 0000000..fcaa11e
--- /dev/null
@@ -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 <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+#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$".
+ */
index 074384b65af979a3168cd326cf8f97a6b322f604..756c4773d5b39437e8a6bf9c77fb08726f098953 100644 (file)
@@ -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
 #ifndef _CUPS_DEBUG_H_
 #  define _CUPS_DEBUG_H_
 
-/*
- * Include necessary headers...
- */
-
-#  include <stdio.h>
-
 /*
  * The debug macros are used if you compile with DEBUG defined.
  *
  */
 
 #  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_ */
 
 /*
index bafe52f1443e64518bc1f361234df30e18d178e3..a4c8264132ea7f01f083ed08d6f08fac225f54fc 100644 (file)
@@ -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 */
 
  /*
index 494b1d45e26b31c46b9950e2ff880f441aac8b11..da76ea36e0c5f48e21a837541167805e2d6fc687 100644 (file)
@@ -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
     {
index 0fb288b1a1e7ea4d1b847f37ff0818d976506560..335623eae88cf7145ea4c9738033254fcebb6d1b 100644 (file)
@@ -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 :
index a73d8fa58529f38d7cab311911afac1ed1ad9966..05a32cc71ffd975f7113db4f0592881e24d70ad7 100644 (file)
@@ -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 (file)
index 0000000..6843e5a
--- /dev/null
@@ -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$".
+ */
index 53dcb0985d4c9474ec38cf4fad6b665ac31a00db..6849f424cfe4f1140db0dfb2b8804d0a72c48f08 100644 (file)
@@ -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 <stdlib.h>
 
 
@@ -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);
index 0aacc0cc8f0248752a7733350253ff036eab197a..a735f01ab5e840e0e6bb98ad97ae3bf30ae03a1a 100644 (file)
@@ -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 */
 
index 6fc5a1243c86b310373e433f1e0da19f623b93dd..6d645053cae98af13c81b45b451818277a423e75 100644 (file)
@@ -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 */
 
  /*
index e48c174c61f2dee86aa292323d1a36c32815b5d6..dabf218ce15e9ca51721c2fdba176a4c9f3dde91 100644 (file)
@@ -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
  * 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);
index eaf48500239a148b6ca55dcf65cfe90bda3ef722..945dc4f6381c96fc576803eeea35f5bc16eb7f06 100644 (file)
@@ -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 */
   }
 
index 9a5e0931ef684bad69645d7f0cf1430c8516b592..0749ec2a1b13a6a32ad0bfc8b558d41029547b89 100644 (file)
@@ -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);
 }
index e08bde6262830cafea23d7bde39994e4e49582c5..eb041b0ca41b600d1b868c7ececd44386f18e396 100644 (file)
@@ -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);
     }
index 8271f59ace2cbc9893ddf1cd5d1897fb52166717..4a689e384f0b83c9603265627dcf26c0c3604819 100644 (file)
@@ -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
index fc981e2d153b1d47c68774ece54e148b5f8a2387..17453961c219df5d605ee8b0720d11b79773a9a6 100644 (file)
@@ -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);
index 0dbb0b8d1859c97c048896fe02af768b120366a9..c0fdc911d62181669919aa391ac611e43559826d 100644 (file)
@@ -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 */
 
index f8c714d13e364f37acaf3fa6ccc2c53a2d9bcfc8..f313c0f7619568509b3824cbb7f90260bd316fbd 100644 (file)
@@ -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
index 99cf9ff5a5144f6a182a72b0e34db4e8f1560f49..e3465def0bf871e630181394dafc5dd8fb5e9bbd 100644 (file)
@@ -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? */
index a20d0c507ac11e7d4ce95bd0773b64bd579c0f3f..c3ec0ef6b461eb654d5d3017b8fa149c1e4c761e 100644 (file)
@@ -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);
index 6a0bd9057b7f01a7b90ba8f89590157b32328ed2..3b9b9d515115548243228ea644a732fe9ef0efae 100644 (file)
@@ -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 <zlib.h>
 #endif /* HAVE_LIBZ */
+#include <fcntl.h>
 
 
 /*
@@ -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...
     */
index 7c7e4f406f1f00255d589e0e663011c52ec9e761..ba9c62ee9747660136dfdf24656709cbd960fdf6 100644 (file)
@@ -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)
   {
index 654edaf27c279fc51aee666211df277bba586623..b6eb2ab816760fbb4848228eb24ec4cf62a85b25 100644 (file)
@@ -320,8 +320,6 @@ div.contents ul.subcontents li {
 <li><a href="#cupsGetDest" title="Get the named destination from the list.">cupsGetDest</a></li>
 <li><a href="#cupsGetDests" title="Get the list of destinations from the default server.">cupsGetDests</a></li>
 <li><a href="#cupsGetDests2" title="Get the list of destinations from the specified server.">cupsGetDests2</a></li>
-<li><a href="#cupsGetFd" title="Get a file from the server.">cupsGetFd</a></li>
-<li><a href="#cupsGetFile" title="Get a file from the server.">cupsGetFile</a></li>
 <li><a href="#cupsGetJobs" title="Get the jobs from the default server.">cupsGetJobs</a></li>
 <li><a href="#cupsGetJobs2" title="Get the jobs from the specified server.">cupsGetJobs2</a></li>
 <li><a href="#cupsGetNamedDest" title="Get options for the named destination.">cupsGetNamedDest</a></li>
@@ -351,8 +349,6 @@ server.">cupsPrintFile2</a></li>
 default server.">cupsPrintFiles</a></li>
 <li><a href="#cupsPrintFiles2" title="Print one or more files to a printer or class on the
 specified server.">cupsPrintFiles2</a></li>
-<li><a href="#cupsPutFd" title="Put a file on the server.">cupsPutFd</a></li>
-<li><a href="#cupsPutFile" title="Put a file on the server.">cupsPutFile</a></li>
 <li><a href="#cupsRemoveDest" title="Remove a destination from the destination list.">cupsRemoveDest</a></li>
 <li><a href="#cupsRemoveOption" title="Remove an option from an option array.">cupsRemoveOption</a></li>
 <li><a href="#cupsServer" title="Return the hostname/address of the default server.">cupsServer</a></li>
@@ -371,6 +367,7 @@ specified server.">cupsPrintFiles2</a></li>
 </ul>
 <li><a href="#TYPES">Data Types</a><ul class="code">
        <li><a href="#cups_dest_t" title="Destination">cups_dest_t</a></li>
+       <li><a href="#cups_device_cb_t" title="Device callback ">cups_device_cb_t</a></li>
        <li><a href="#cups_job_t" title="Job">cups_job_t</a></li>
        <li><a href="#cups_option_t" title="Printer Options">cups_option_t</a></li>
        <li><a href="#cups_password_cb_t" title="Password callback">cups_password_cb_t</a></li>
@@ -1170,52 +1167,6 @@ printer-state-reasons, and printer-type attributes as options.<br>
 Use the <a href="#cupsFreeDests"><code>cupsFreeDests</code></a> function to free the destination list and
 the <a href="#cupsGetDest"><code>cupsGetDest</code></a> function to find a particular destination.
 
-</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsGetFd">cupsGetFd</a></h3>
-<p class="description">Get a file from the server.</p>
-<p class="code">
-http_status_t cupsGetFd (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;http_t *http,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int fd<br>
-);</p>
-<h4 class="parameters">Parameters</h4>
-<dl>
-<dt>http</dt>
-<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
-<dt>resource</dt>
-<dd class="description">Resource name</dd>
-<dt>fd</dt>
-<dd class="description">File descriptor</dd>
-</dl>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">HTTP status</p>
-<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function returns <code>HTTP_OK</code> when the file is successfully retrieved.
-
-</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsGetFile">cupsGetFile</a></h3>
-<p class="description">Get a file from the server.</p>
-<p class="code">
-http_status_t cupsGetFile (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;http_t *http,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *filename<br>
-);</p>
-<h4 class="parameters">Parameters</h4>
-<dl>
-<dt>http</dt>
-<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
-<dt>resource</dt>
-<dd class="description">Resource name</dd>
-<dt>filename</dt>
-<dd class="description">Filename</dd>
-</dl>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">HTTP status</p>
-<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function returns <code>HTTP_OK</code> when the file is successfully retrieved.
-
 </p>
 <h3 class="function"><a name="cupsGetJobs">cupsGetJobs</a></h3>
 <p class="description">Get the jobs from the default server.</p>
@@ -1719,54 +1670,6 @@ int cupsPrintFiles2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">Job ID or 0 on error</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsPutFd">cupsPutFd</a></h3>
-<p class="description">Put a file on the server.</p>
-<p class="code">
-http_status_t cupsPutFd (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;http_t *http,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int fd<br>
-);</p>
-<h4 class="parameters">Parameters</h4>
-<dl>
-<dt>http</dt>
-<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
-<dt>resource</dt>
-<dd class="description">Resource name</dd>
-<dt>fd</dt>
-<dd class="description">File descriptor</dd>
-</dl>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">HTTP status</p>
-<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function returns <code>HTTP_CREATED</code> when the file is stored
-successfully.
-
-</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsPutFile">cupsPutFile</a></h3>
-<p class="description">Put a file on the server.</p>
-<p class="code">
-http_status_t cupsPutFile (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;http_t *http,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *filename<br>
-);</p>
-<h4 class="parameters">Parameters</h4>
-<dl>
-<dt>http</dt>
-<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
-<dt>resource</dt>
-<dd class="description">Resource name</dd>
-<dt>filename</dt>
-<dd class="description">Filename</dd>
-</dl>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">HTTP status</p>
-<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function returns <code>HTTP_CREATED</code> when the file is stored
-successfully.
-
-</p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.3&nbsp;</span><a name="cupsRemoveDest">cupsRemoveDest</a></h3>
 <p class="description">Remove a destination from the destination list.</p>
 <p class="code">
@@ -2049,6 +1952,11 @@ const char *cupsUser (void);</p>
 <p class="code">
 typedef struct <a href="#cups_dest_s">cups_dest_s</a> cups_dest_t;
 </p>
+<h3 class="typedef"><span class="info">&nbsp;CUPS 1.4&nbsp;</span><a name="cups_device_cb_t">cups_device_cb_t</a></h3>
+<p class="description">Device callback </p>
+<p class="code">
+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);
+</p>
 <h3 class="typedef"><a name="cups_job_t">cups_job_t</a></h3>
 <p class="description">Job</p>
 <p class="code">
@@ -2062,7 +1970,7 @@ typedef struct <a href="#cups_option_s">cups_option_s</a> cups_option_t;
 <h3 class="typedef"><a name="cups_password_cb_t">cups_password_cb_t</a></h3>
 <p class="description">Password callback</p>
 <p class="code">
-typedef const char *(*cups_password_cb_t)(const char *);
+typedef const char *(*cups_password_cb_t)(const char *prompt);
 </p>
 <h3 class="typedef"><a name="cups_ptype_t">cups_ptype_t</a></h3>
 <p class="description">Printer type/capability bits</p>
index 04fc4a06bcfdb85e5e62ea77e30594c667c0bce6..0455237028e12ec183596387cda8ed471936e68f 100644 (file)
@@ -304,7 +304,12 @@ div.contents ul.subcontents li {
 <li><a href="#cupsDoRequest" title="Do an IPP request.">cupsDoRequest</a></li>
 <li><a href="#cupsEncodeOptions" title="Encode printer options into IPP attributes.">cupsEncodeOptions</a></li>
 <li><a href="#cupsEncodeOptions2" title="Encode printer options into IPP attributes for a group.">cupsEncodeOptions2</a></li>
+<li><a href="#cupsGetDevices" title="Get available printer devices.">cupsGetDevices</a></li>
+<li><a href="#cupsGetFd" title="Get a file from the server.">cupsGetFd</a></li>
+<li><a href="#cupsGetFile" title="Get a file from the server.">cupsGetFile</a></li>
 <li><a href="#cupsGetResponse" title="Get a response to an IPP request.">cupsGetResponse</a></li>
+<li><a href="#cupsPutFd" title="Put a file on the server.">cupsPutFd</a></li>
+<li><a href="#cupsPutFile" title="Put a file on the server.">cupsPutFile</a></li>
 <li><a href="#cupsReadResponseData" title="Read additional data after the IPP response.">cupsReadResponseData</a></li>
 <li><a href="#cupsSendRequest" title="Send an IPP request.">cupsSendRequest</a></li>
 <li><a href="#cupsWriteRequestData" title="Write additional data after an IPP request.">cupsWriteRequestData</a></li>
@@ -954,6 +959,84 @@ void cupsEncodeOptions2 (<br>
 function multiple times for each group, or use cupsEncodeOptions()
 to add the standard groups.
 
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.4&nbsp;</span><a name="cupsGetDevices">cupsGetDevices</a></h3>
+<p class="description">Get available printer devices.</p>
+<p class="code">
+ipp_status_t cupsGetDevices (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int timeout,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *exclude_schemes,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;cups_device_cb_t callback,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;void *user_data<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
+<dt>timeout</dt>
+<dd class="description">Timeout in seconds or <code>CUPS_TIMEOUT_DEFAULT</code></dd>
+<dt>exclude_schemes</dt>
+<dd class="description">Comma-separated URI schemes to exclude or <code>CUPS_EXCLUDE_NONE</code></dd>
+<dt>callback</dt>
+<dd class="description">Callback function</dd>
+<dt>user_data</dt>
+<dd class="description">User data pointer</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Request status - <code>IPP_OK</code> on success.</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">This function sends a CUPS-Get-Devices request and streams the discovered
+devices to the specified callback function. The &quot;timeout&quot; parameter controls
+how long the request lasts, while the &quot;exclude_schemes&quot; parameter provides
+a comma-delimited list of backends to omit from the request.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsGetFd">cupsGetFd</a></h3>
+<p class="description">Get a file from the server.</p>
+<p class="code">
+http_status_t cupsGetFd (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int fd<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
+<dt>resource</dt>
+<dd class="description">Resource name</dd>
+<dt>fd</dt>
+<dd class="description">File descriptor</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">HTTP status</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">This function returns <code>HTTP_OK</code> when the file is successfully retrieved.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsGetFile">cupsGetFile</a></h3>
+<p class="description">Get a file from the server.</p>
+<p class="code">
+http_status_t cupsGetFile (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *filename<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
+<dt>resource</dt>
+<dd class="description">Resource name</dd>
+<dt>filename</dt>
+<dd class="description">Filename</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">HTTP status</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">This function returns <code>HTTP_OK</code> when the file is successfully retrieved.
+
 </p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.4&nbsp;</span><a name="cupsGetResponse">cupsGetResponse</a></h3>
 <p class="description">Get a response to an IPP request.</p>
@@ -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.
 
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsPutFd">cupsPutFd</a></h3>
+<p class="description">Put a file on the server.</p>
+<p class="code">
+http_status_t cupsPutFd (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int fd<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
+<dt>resource</dt>
+<dd class="description">Resource name</dd>
+<dt>fd</dt>
+<dd class="description">File descriptor</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">HTTP status</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">This function returns <code>HTTP_CREATED</code> when the file is stored
+successfully.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.1.20&nbsp;</span><a name="cupsPutFile">cupsPutFile</a></h3>
+<p class="description">Put a file on the server.</p>
+<p class="code">
+http_status_t cupsPutFile (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *resource,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *filename<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server or <code>CUPS_HTTP_DEFAULT</code></dd>
+<dt>resource</dt>
+<dd class="description">Resource name</dd>
+<dt>filename</dt>
+<dd class="description">Filename</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">HTTP status</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">This function returns <code>HTTP_CREATED</code> when the file is stored
+successfully.
+
 </p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.4&nbsp;</span><a name="cupsReadResponseData">cupsReadResponseData</a></h3>
 <p class="description">Read additional data after the IPP response.</p>
@@ -1019,7 +1150,7 @@ http_status_t cupsSendRequest (<br>
 <dt>resource</dt>
 <dd class="description">Resource path</dd>
 <dt>length</dt>
-<dd class="description">Length of data to follow or CUPS_LENGTH_VARIABLE</dd>
+<dd class="description">Length of data to follow or <code>CUPS_LENGTH_VARIABLE</code></dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">Initial HTTP status</p>
index 0d768c9fb173406a85ddd00afb560bdfd718b601..e5d0f37623d5badc858963700a79b9d0c508dfb1 100644 (file)
@@ -1571,6 +1571,12 @@ CUPS-Get-Devices request:
        <dd>The client OPTIONALLY supplies a device class keyword to select
        which devices are returned.
 
+       <dt>"exclude-schemes" (1setOf name) :<span class='info'>CUPS 1.4</span>
+
+       <dd>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.
+
        <dt>"limit" (integer (1:MAX)):
 
        <dd>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'.
 
+       <dt>"timeout" (integer (1:MAX)) :<span class='info'>CUPS 1.4</span>
+
+       <dd>The client OPTIONALLY supplies this attribute limiting the number of
+       devices that are returned.
+
 </dl>
 
 <h4>CUPS-Get-Devices Response</h4>
index f4e8c39837211a1e2479483d71efd3569d1b6793..44c2eabfb3a440a3e358aa217a1296ec889aaf98 100644 (file)
@@ -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));
 }
 
 
index 0cc782f9c5b3f28a49e645a1ec10681dab62099e..945c8f40a9a1a2217a48b8b84e8190cfecc1ecd6 100644 (file)
@@ -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 */
 
index f1abb52bfb2f91a4ea055b57af606ed4ed3e593b..0529dd144070f2c0d78a07d426225e08b00f3138 100644 (file)
@@ -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
index 62ecb347b8a089cf9748cb14d40271c902f021bf..b528bc06ba9d4b947ec86a3b5a018509e6a573dd 100644 (file)
@@ -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)
   {
    /*
index cb62278fd7961a839d8dfb50d9abe7f4eb6be7a5..956ae88abc9ed69da2f3598ce084ba49546fd0e0 100644 (file)
@@ -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)
index a83409e950ab3a679633e5507b04bca6c2e75443..3376065fe7e2edd9991c24ac025b79bac5ae1a83 100644 (file)
@@ -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...
index c5767a6b143d11c820d5ed034d6a1f52c3b82968..03f1199bbabd615d24dfd394e291bf90a01e2da9 100644 (file)
@@ -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("<rss version=\"2.0\">\n", fp);
   fputs("  <channel>\n", fp);
   fputs("    <title>CUPS RSS Feed</title>\n", fp);
-  fprintf(fp, "    <link>%s</link>\n", baseurl);
+
+  href = xml_escape(baseurl);
+  fprintf(fp, "    <link>%s</link>\n", href);
+  free(href);
+
   fputs("    <description>CUPS RSS Feed</description>\n", fp);
   fputs("    <generator>" CUPS_SVERSION "</generator>\n", fp);
   fputs("    <ttl>1</ttl>\n", fp);
index 29de91f673968b1b5139b30393e640fd353e65cb..db9528e6d09cc3fb3c28aa0bae69d4e1ac141f03 100644 (file)
@@ -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"))
index 94ddc900a9b5a22793f031f50d77ad24f3b52c0a..ba016434a98243c2fcc2e95de9e959c725ed78c8 100644 (file)
@@ -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)
index 25475564897da5730db00429945145cd580a9b5b..c8e814886333fa0b123c8d457aab0151769b7ecf 100644 (file)
@@ -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"))
index 385037ea244d35287dbbe5a08e1a8e9c13b2634d..9c5b6991f5d236916fa61d7356fe75ecfb9d3976 100644 (file)
  *
  * 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.
  */
 
 /*
 #include <cups/array.h>
 #include <cups/dir.h>
 #include <fcntl.h>
+#include <sys/wait.h>
+#include <poll.h>
+
+
+/*
+ * 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);                          /* </dev/null */
     open("/dev/null", O_RDONLY);
@@ -530,33 +723,34 @@ run_backend(const char *backend,  /* I - Backend to run */
     close(fds[0]);                     /* Close copies of pipes */
     close(fds[1]);
 
-    execl(backend, backend, (char *)0);        /* Run it! */
-    fprintf(stderr, "ERROR: Unable to execute \"%s\" - %s\n", backend,
-            strerror(errno));
+    execl(program, name, (char *)0);   /* Run it! */
+    fprintf(stderr, "ERROR: [cups-deviced] Unable to execute \"%s\" - %s\n",
+            program, strerror(errno));
     exit(1);
   }
 
  /*
-  * Parent comes here, make a FILE * from the input side of the pipe...
+  * Parent comes here, allocate a backend and open the input side of the
+  * pipe...
   */
 
-  close(fds[1]);
+  fprintf(stderr, "DEBUG: [cups-deviced] Started backend %s (PID %d)\n",
+          program, backend->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);
 }
 
 
index 30231306d3bb8c1ae60c75cf3646ac4c9d674657..73344b6aed60d7c9bbf573299ac2cf498bb14d41 100644 (file)
@@ -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);
 }
index 9ecca1cde2e80e952f08858a703a5ef6976462f8..f29006b869cee0508328772cf2981675feda3710 100644 (file)
@@ -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))
   {
index 8ecd4309e274f5bd38937966474604601d1f4e19..e831920a065a44a0873d5b6605640cd30f8dffa0 100644 (file)
@@ -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... */
 
index b8697c2c8c95f572074b65a0b70f969e9bf3e826..137304994c7009b4ebe32486fb3aa35f008a84e7 100644 (file)
@@ -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.
  */
  * 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);