}
-/*
- * End of "$Id$".
- */
-/*
- * "$Id$"
- *
- * DNS-SD discovery backend 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"
- * "LICENSE" which should have been included with this file. If this
- * 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:
- *
- * main() - Browse for printers.
- * browse_callback() - Browse devices.
- * browse_local_callback() - Browse local devices.
- * compare_devices() - Compare two devices.
- * get_device() - Create or update a device.
- * query_callback() - Process query data.
- * unquote() - Unquote a name string.
- */
-
-/*
- * Include necessary headers.
- */
-
-#include "backend-private.h"
-#include <cups/array.h>
-#include <dns_sd.h>
-
-
-/*
- * Device structure...
- */
-
-typedef enum
-{
- CUPS_DEVICE_PRINTER = 0, /* lpd://... */
- CUPS_DEVICE_IPP, /* ipp://... */
- CUPS_DEVICE_FAX_IPP, /* ipp://... */
- CUPS_DEVICE_PDL_DATASTREAM, /* socket://... */
- CUPS_DEVICE_RIOUSBPRINT /* riousbprint://... */
-} cups_devtype_t;
-
-
-typedef struct
-{
- DNSServiceRef ref; /* Service reference for resolve */
- char *name, /* Service name */
- *domain, /* Domain name */
- *fullName, /* Full name */
- *make_and_model; /* Make and model from TXT record */
- cups_devtype_t type; /* Device registration type */
- int cups_shared, /* CUPS shared printer? */
- sent; /* Did we list the device? */
-} cups_device_t;
-
-
-/*
- * Local functions...
- */
-
-static void browse_callback(DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char *serviceName,
- const char *regtype,
- const char *replyDomain, void *context);
-static void browse_local_callback(DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char *serviceName,
- const char *regtype,
- const char *replyDomain,
- void *context);
-static int compare_devices(cups_device_t *a, cups_device_t *b);
-static void exec_backend(char **argv);
-static cups_device_t *get_device(cups_array_t *devices,
- const char *serviceName,
- const char *regtype,
- const char *replyDomain);
-static void query_callback(DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char *fullName, uint16_t rrtype,
- uint16_t rrclass, uint16_t rdlen,
- const void *rdata, uint32_t ttl,
- void *context);
-static void unquote(char *dst, const char *src, size_t dstsize);
-
-
-/*
- * 'main()' - Browse for printers.
- */
-
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line args */
- char *argv[]) /* I - Command-line arguments */
-{
- DNSServiceRef main_ref, /* Main service reference */
- fax_ipp_ref, /* IPP fax service reference */
- ipp_ref, /* IPP service reference */
- ipp_tls_ref, /* IPP w/TLS service reference */
- local_fax_ipp_ref, /* Local IPP fax service reference */
- local_ipp_ref, /* Local IPP service reference */
- local_ipp_tls_ref, /* Local IPP w/TLS service reference */
- local_printer_ref, /* Local LPD service reference */
- pdl_datastream_ref, /* AppSocket service reference */
- printer_ref, /* LPD service reference */
- riousbprint_ref; /* Remote IO service reference */
- int fd; /* Main file descriptor */
- fd_set input; /* Input set for select() */
- struct timeval timeout; /* Timeout for select() */
- cups_array_t *devices; /* Device array */
- cups_device_t *device; /* Current device */
-
-
- /*
- * Check command-line...
- */
-
- setbuf(stderr, NULL);
-
- if (argc >= 6)
- exec_backend(argv);
- else if (argc != 1)
- {
- fputs("Usage: mdns job user title copies options [filename(s)]\n", stderr);
- return (1);
- }
-
- /*
- * Create an array to track devices...
- */
-
- devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);
-
- /*
- * Browse for different kinds of printers...
- */
-
- if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
- {
- perror("ERROR: Unable to create service connection");
- return (1);
- }
-
- fd = DNSServiceRefSockFD(main_ref);
-
- fax_ipp_ref = main_ref;
- DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0,
- "_fax-ipp._tcp", NULL, browse_callback, devices);
-
- ipp_ref = main_ref;
- DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
- "_ipp._tcp", NULL, browse_callback, devices);
-
- ipp_tls_ref = main_ref;
- DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
- "_ipp-tls._tcp", NULL, browse_callback, devices);
-
- local_fax_ipp_ref = main_ref;
- DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_fax-ipp._tcp", NULL, browse_local_callback, devices);
-
- local_ipp_ref = main_ref;
- DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_ipp._tcp", NULL, browse_local_callback, devices);
-
- local_ipp_tls_ref = main_ref;
- DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_ipp-tls._tcp", NULL, browse_local_callback, devices);
-
- local_printer_ref = main_ref;
- DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_printer._tcp", NULL, browse_local_callback, devices);
-
- pdl_datastream_ref = main_ref;
- DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
- "_pdl-datastream._tcp", NULL, browse_callback, devices);
-
- printer_ref = main_ref;
- DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0,
- "_printer._tcp", NULL, browse_callback, devices);
-
- riousbprint_ref = main_ref;
- DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
- "_riousbprint._tcp", NULL, browse_callback, devices);
-
- /*
- * Loop until we are killed...
- */
-
- for (;;)
- {
- FD_ZERO(&input);
- FD_SET(fd, &input);
-
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-
- if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
- continue;
-
- if (FD_ISSET(fd, &input))
- {
- /*
- * Process results of our browsing...
- */
-
- DNSServiceProcessResult(main_ref);
- }
- else
- {
- /*
- * Announce any devices we've found...
- */
-
- char device_uri[1024]; /* Device URI */
- static const char * const schemes[] =
- { "lpd", "ipp", "ipp", "socket", "riousbprint" };
- /* URI schemes for devices */
-
-
- for (device = (cups_device_t *)cupsArrayFirst(devices);
- device;
- device = (cups_device_t *)cupsArrayNext(devices))
- if (!device->ref && !device->sent)
- {
- /*
- * Found the device, now get the TXT record(s) for it...
- */
-
- device->ref = main_ref;
-
- fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);
-
- if (DNSServiceQueryRecord(&(device->ref),
- kDNSServiceFlagsShareConnection,
- 0, device->fullName, kDNSServiceType_TXT,
- kDNSServiceClass_IN, query_callback,
- devices) != kDNSServiceErr_NoError)
- fputs("ERROR: Unable to query for TXT records!\n", stderr);
- }
- else if (!device->sent)
- {
- /*
- * Got the TXT records, now report the device...
- */
-
- DNSServiceRefDeallocate(device->ref);
- device->ref = 0;
-
- httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri),
- schemes[device->type], NULL, device->fullName, 0,
- device->cups_shared ? "/cups" : "");
-
- printf("network %s \"%s\" \"%s\"\n", device_uri,
- device->make_and_model ? device->make_and_model : "Unknown",
- device->name);
-
- device->sent = 1;
- }
- }
- }
-}
-
-
-/*
- * 'browse_callback()' - Browse devices.
- */
-
-static void
-browse_callback(
- DNSServiceRef sdRef, /* I - Service reference */
- DNSServiceFlags flags, /* I - Option flags */
- uint32_t interfaceIndex, /* I - Interface number */
- DNSServiceErrorType errorCode, /* I - Error, if any */
- const char *serviceName, /* I - Name of service/device */
- const char *regtype, /* I - Type of service */
- const char *replyDomain, /* I - Service domain */
- void *context) /* I - Devices array */
-{
- fprintf(stderr, "DEBUG2: browse_callback(sdRef=%p, flags=%x, "
- "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
- "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
- sdRef, flags, interfaceIndex, errorCode,
- serviceName ? serviceName : "(null)",
- regtype ? regtype : "(null)",
- replyDomain ? replyDomain : "(null)",
- context);
-
- /*
- * Only process "add" data...
- */
-
- if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
- return;
-
- /*
- * Get the device...
- */
-
- get_device((cups_array_t *)context, serviceName, regtype, replyDomain);
-}
-
-
-/*
- * 'browse_local_callback()' - Browse local devices.
- */
-
-static void
-browse_local_callback(
- DNSServiceRef sdRef, /* I - Service reference */
- DNSServiceFlags flags, /* I - Option flags */
- uint32_t interfaceIndex, /* I - Interface number */
- DNSServiceErrorType errorCode, /* I - Error, if any */
- const char *serviceName, /* I - Name of service/device */
- const char *regtype, /* I - Type of service */
- const char *replyDomain, /* I - Service domain */
- void *context) /* I - Devices array */
-{
- cups_device_t *device; /* Device */
-
-
- fprintf(stderr, "DEBUG2: browse_local_callback(sdRef=%p, flags=%x, "
- "interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", "
- "regtype=\"%s\", replyDomain=\"%s\", context=%p)\n",
- sdRef, flags, interfaceIndex, errorCode,
- serviceName ? serviceName : "(null)",
- regtype ? regtype : "(null)",
- replyDomain ? replyDomain : "(null)",
- context);
-
- /*
- * Only process "add" data...
- */
-
- if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
- return;
-
- /*
- * Get the device...
- */
-
- device = get_device((cups_array_t *)context, serviceName, regtype,
- replyDomain);
-
- /*
- * Hide locally-registered devices...
- */
-
- fprintf(stderr, "DEBUG: Hiding local printer \"%s\"...\n",
- device->fullName);
- device->sent = 1;
-}
-
-
-/*
- * 'compare_devices()' - Compare two devices.
- */
-
-static int /* O - Result of comparison */
-compare_devices(cups_device_t *a, /* I - First device */
- cups_device_t *b) /* I - Second device */
-{
- int result = strcmp(a->name, b->name);
-
- if (result)
- return (result);
- else
- return (strcmp(a->domain, b->domain));
-}
-
-
-/*
- * 'exec_backend()' - Execute the backend that corresponds to the
- * resolved service name.
- */
-
-static void
-exec_backend(char **argv) /* I - Command-line arguments */
-{
- const char *resolved_uri, /* Resolved device URI */
- *cups_serverbin; /* Location of programs */
- char scheme[1024], /* Scheme from URI */
- *ptr, /* Pointer into scheme */
- filename[1024]; /* Backend filename */
-
-
- /*
- * Resolve the device URI...
- */
-
- resolved_uri = backendResolveURI(argv);
-
- /*
- * Extract the scheme from the URI...
- */
-
- strlcpy(scheme, resolved_uri, sizeof(scheme));
- if ((ptr = strchr(scheme, ':')) != NULL)
- *ptr = '\0';
-
- /*
- * Get the filename of the backend...
- */
-
- if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
- cups_serverbin = CUPS_SERVERBIN;
-
- snprintf(filename, sizeof(filename), "%s/backend/%s", cups_serverbin, scheme);
-
- /*
- * Overwrite the device URIs and run the new backend...
- */
-
- setenv("DEVICE_URI", resolved_uri, 1);
-
- argv[0] = (char *)resolved_uri;
-
- fprintf(stderr, "DEBUG: Executing backend \"%s\"...\n", filename);
-
- execv(filename, argv);
-
- fprintf(stderr, "ERROR: Unable to execute backend \"%s\": %s\n", filename,
- strerror(errno));
- exit(CUPS_BACKEND_STOP);
-}
-
-
-/*
- * 'get_device()' - Create or update a device.
- */
-
-static cups_device_t * /* O - Device */
-get_device(cups_array_t *devices, /* I - Device array */
- const char *serviceName, /* I - Name of service/device */
- const char *regtype, /* I - Type of service */
- const char *replyDomain) /* I - Service domain */
-{
- cups_device_t key, /* Search key */
- *device; /* Device */
- char fullName[1024]; /* Full name for query */
-
-
- /*
- * See if this is a new device...
- */
-
- key.name = (char *)serviceName;
- key.domain = (char *)replyDomain;
-
- if (!strcmp(regtype, "_ipp._tcp.") ||
- !strcmp(regtype, "_ipp-tls._tcp."))
- key.type = CUPS_DEVICE_IPP;
- else if (!strcmp(regtype, "_fax-ipp._tcp."))
- key.type = CUPS_DEVICE_FAX_IPP;
- else if (!strcmp(regtype, "_printer._tcp."))
- key.type = CUPS_DEVICE_PRINTER;
- else if (!strcmp(regtype, "_pdl-datastream._tcp."))
- key.type = CUPS_DEVICE_PDL_DATASTREAM;
- else
- key.type = CUPS_DEVICE_RIOUSBPRINT;
-
- if ((device = cupsArrayFind(devices, &key)) != NULL)
- {
- /*
- * No, see if this registration is a higher priority protocol...
- */
-
- if (key.type > device->type)
- {
- fprintf(stderr, "DEBUG: Updating \"%s\" to \"%s.%s%s\"...\n",
- device->fullName, serviceName, regtype, replyDomain);
-
- device->type = key.type;
- }
- }
- else
- {
- /*
- * Yes, add the device...
- */
-
- fprintf(stderr, "DEBUG: Found \"%s.%s%s\"...\n", serviceName, regtype,
- replyDomain);
-
- device = calloc(sizeof(cups_device_t), 1);
- device->name = strdup(serviceName);
- device->domain = strdup(replyDomain);
- device->type = key.type;
-
- cupsArrayAdd(devices, device);
- }
-
- /*
- * Update the "full name" of this service, which is used for queries...
- */
-
- snprintf(fullName, sizeof(fullName), "%s.%s%s", serviceName, regtype,
- replyDomain);
-
- if (device->fullName)
- free(device->fullName);
-
- device->fullName = strdup(fullName);
-
- return (device);
-}
-
-
-/*
- * 'query_callback()' - Process query data.
- */
-
-static void
-query_callback(
- DNSServiceRef sdRef, /* I - Service reference */
- DNSServiceFlags flags, /* I - Data flags */
- uint32_t interfaceIndex, /* I - Interface */
- DNSServiceErrorType errorCode, /* I - Error, if any */
- const char *fullName, /* I - Full service name */
- uint16_t rrtype, /* I - Record type */
- uint16_t rrclass, /* I - Record class */
- uint16_t rdlen, /* I - Length of record data */
- const void *rdata, /* I - Record data */
- uint32_t ttl, /* I - Time-to-live */
- void *context) /* I - Devices array */
-{
- cups_array_t *devices; /* Device array */
- char name[1024], /* Service name */
- *ptr; /* Pointer into name */
- cups_device_t key, /* Search key */
- *device; /* Device */
-
-
- fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
- "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
- "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, "
- "context=%p)\n",
- sdRef, flags, interfaceIndex, errorCode,
- fullName ? fullName : "(null)", rrtype, rrclass, rdlen, rdata, ttl,
- context);
-
- /*
- * Only process "add" data...
- */
-
- if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
- return;
-
- /*
- * Lookup the service in the devices array.
- */
-
- devices = (cups_array_t *)context;
- key.name = name;
-
- unquote(name, fullName, sizeof(name));
-
- if ((key.domain = strstr(name, "._tcp.")) != NULL)
- key.domain += 6;
- else
- key.domain = (char *)"local.";
-
- if ((ptr = strstr(name, "._")) != NULL)
- *ptr = '\0';
-
- if ((device = cupsArrayFind(devices, &key)) != NULL)
- {
- /*
- * Found it, pull out the make and model from the TXT record and save it...
- */
-
- const void *value; /* Pointer to value */
- uint8_t valueLen; /* Length of value (max 255) */
- char make_and_model[512], /* Manufacturer and model */
- model[256]; /* Model */
-
-
- if ((value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MFG",
- &valueLen)) == NULL)
- value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MANUFACTURER", &valueLen);
-
- if (value && valueLen)
- {
- memcpy(make_and_model, value, valueLen);
- make_and_model[valueLen] = '\0';
- }
- else
- make_and_model[0] = '\0';
-
- if ((value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MDL",
- &valueLen)) == NULL)
- value = TXTRecordGetValuePtr(rdlen, rdata, "usb_MODEL", &valueLen);
-
- if (value && valueLen)
- {
- memcpy(model, value, valueLen);
- model[valueLen] = '\0';
- }
- else if ((value = TXTRecordGetValuePtr(rdlen, rdata, "product",
- &valueLen)) != NULL && valueLen > 2)
- {
- memcpy(model, value + 1, valueLen - 2);
- model[valueLen - 2] = '\0';
-
- if (!strcasecmp(model, "GPL Ghostscript") ||
- !strcasecmp(model, "GNU Ghostscript") ||
- !strcasecmp(model, "ESP Ghostscript"))
- {
- if ((value = TXTRecordGetValuePtr(rdlen, rdata, "ty",
- &valueLen)) != NULL)
- {
- memcpy(model, value, valueLen);
- model[valueLen] = '\0';
-
- if ((ptr = strchr(model, ',')) != NULL)
- *ptr = '\0';
- }
- else
- strcpy(model, "Unknown");
- }
- }
- else
- strcpy(model, "Unknown");
-
- if (device->make_and_model)
- free(device->make_and_model);
-
- if (make_and_model[0])
- {
- strlcat(make_and_model, " ", sizeof(make_and_model));
- strlcat(make_and_model, model, sizeof(make_and_model));
- device->make_and_model = strdup(make_and_model);
- }
- else
- device->make_and_model = strdup(model);
-
- if (device->type == CUPS_DEVICE_IPP &&
- (value = TXTRecordGetValuePtr(rdlen, rdata, "printer-type",
- &valueLen)) != NULL)
- {
- /*
- * This is a CUPS printer!
- */
-
- device->cups_shared = 1;
- }
- }
- else
- fprintf(stderr, "DEBUG: Ignoring TXT record for \"%s\"...\n", fullName);
-}
-
-
-/*
- * 'unquote()' - Unquote a name string.
- */
-
-static void
-unquote(char *dst, /* I - Destination buffer */
- const char *src, /* I - Source string */
- size_t dstsize) /* I - Size of destination buffer */
-{
- char *dstend = dst + dstsize - 1; /* End of destination buffer */
-
-
- while (*src && dst < dstend)
- {
- if (*src == '\\')
- {
- src ++;
- if (isdigit(src[0] & 255) && isdigit(src[1] & 255) &&
- isdigit(src[2] & 255))
- {
- *dst++ = ((((src[0] - '0') * 10) + src[1] - '0') * 10) + src[2] - '0';
- src += 3;
- }
- else
- *dst++ = *src++;
- }
- else
- *dst++ = *src ++;
- }
-
- *dst = '\0';
-}
-
-
/*
* End of "$Id$".
*/
#endif /* HAVE_DNSSD */
-/*
- * End of "$Id$".
- */
-/*
- * "$Id$"
- *
- * Common network APIs for the Common UNIX Printing System (CUPS).
- *
- * Copyright 2007-2008 by Apple Inc.
- * Copyright 2006-2007 by Easy Software Products, all rights reserved.
- *
- * 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"
- * "LICENSE" which should have been included with this file. If this
- * 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 "backend-private.h"
-#include <limits.h>
-#ifdef __hpux
-# include <sys/time.h>
-#else
-# include <sys/select.h>
-#endif /* __hpux */
-#ifdef HAVE_DNSSD
-# include <dns_sd.h>
-#endif /* HAVE_DNSSD */
-
-
-/*
- * Local functions...
- */
-
-#ifdef HAVE_DNSSD
-static void resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char *fullName, const char *hostTarget,
- uint16_t port, uint16_t txtLen,
- const unsigned char *txtRecord, void *context);
-#endif /* HAVE_DNSSD */
-
-
-/*
- * 'backendCheckSideChannel()' - Check the side-channel for pending requests.
- */
-
-
-void
-backendCheckSideChannel(
- int snmp_fd, /* I - SNMP socket */
- http_addr_t *addr) /* I - Address of device */
-{
- fd_set input; /* Select input set */
- struct timeval timeout; /* Select timeout */
-
-
- FD_ZERO(&input);
- FD_SET(CUPS_SC_FD, &input);
-
- timeout.tv_sec = timeout.tv_usec = 0;
-
- if (select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout) > 0)
- backendNetworkSideCB(-1, -1, snmp_fd, addr, 0);
-}
-
-
-/*
- * 'backendNetworkSideCB()' - Handle common network side-channel commands.
- */
-
-void
-backendNetworkSideCB(
- int print_fd, /* I - Print file or -1 */
- int device_fd, /* I - Device file or -1 */
- int snmp_fd, /* I - SNMP socket */
- http_addr_t *addr, /* I - Address of device */
- int use_bc) /* I - Use back-channel data? */
-{
- cups_sc_command_t command; /* Request command */
- cups_sc_status_t status; /* Request/response status */
- char data[2048]; /* Request/response data */
- int datalen; /* Request/response data size */
- const char *device_id; /* 1284DEVICEID env var */
-
-
- datalen = sizeof(data);
-
- if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
- {
- _cupsLangPuts(stderr, _("WARNING: Failed to read side-channel request!\n"));
- return;
- }
-
- switch (command)
- {
- case CUPS_SC_CMD_DRAIN_OUTPUT :
- /*
- * Our sockets disable the Nagle algorithm and data is sent immediately.
- */
-
- if (device_fd < 0)
- status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
- else if (backendDrainOutput(print_fd, device_fd))
- status = CUPS_SC_STATUS_IO_ERROR;
- else
- status = CUPS_SC_STATUS_OK;
-
- datalen = 0;
- break;
-
- case CUPS_SC_CMD_GET_BIDI :
- data[0] = use_bc;
- datalen = 1;
- break;
-
- case CUPS_SC_CMD_GET_DEVICE_ID :
- if (snmp_fd >= 0)
- {
- cups_snmp_t packet; /* Packet from printer */
- static const int ppmPrinterIEEE1284DeviceId[] =
- { CUPS_OID_ppmPrinterIEEE1284DeviceId,1,-1 };
-
- if (_cupsSNMPWrite(snmp_fd, addr, 1, _cupsSNMPDefaultCommunity(),
- CUPS_ASN1_GET_REQUEST, 1,
- ppmPrinterIEEE1284DeviceId))
- {
- if (_cupsSNMPRead(snmp_fd, &packet, 1.0) &&
- packet.object_type == CUPS_ASN1_OCTET_STRING)
- {
- strlcpy(data, packet.object_value.string, sizeof(data));
- datalen = (int)strlen(data);
- break;
- }
- }
- }
-
- if ((device_id = getenv("1284DEVICEID")) != NULL)
- {
- strlcpy(data, device_id, sizeof(data));
- datalen = (int)strlen(data);
- break;
- }
-
- default :
- status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
- datalen = 0;
- break;
- }
-
- cupsSideChannelWrite(command, status, data, datalen, 1.0);
-}
-
-
-/*
- * 'backendResolveURI()' - Get the device URI, resolving as needed.
- */
-
-const char * /* O - Device URI */
-backendResolveURI(char **argv) /* I - Command-line arguments */
-{
- const char *uri; /* Device URI */
- char scheme[32], /* URI components... */
- userpass[256],
- hostname[1024],
- resource[1024];
- int port;
- http_uri_status_t status; /* URI decode status */
-
- /*
- * Get the device URI...
- */
-
- uri = cupsBackendDeviceURI(argv);
-
- if ((status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme,
- sizeof(scheme), userpass, sizeof(userpass),
- hostname, sizeof(hostname), &port,
- resource, sizeof(resource))) < HTTP_URI_OK)
- {
- fprintf(stderr, "ERROR: Bad device URI \"%s\" (%d)!\n", uri, status);
- exit (CUPS_BACKEND_STOP);
- }
-
- /*
- * Resolve it as needed...
- */
-
- if (strstr(hostname, "._tcp"))
- {
-#ifdef HAVE_DNSSD
- DNSServiceRef ref; /* DNS-SD service reference */
- char *regtype, /* Pointer to type in hostname */
- *domain; /* Pointer to domain in hostname */
- static char resolved_uri[HTTP_MAX_URI];
- /* Resolved device URI */
-
- /*
- * Separate the hostname into service name, registration type, and domain...
- */
-
- regtype = strchr(hostname, '.');
- *regtype++ = '\0';
-
- domain = regtype + strlen(regtype) - 1;
- if (domain > regtype && *domain == '.')
- *domain = '\0';
-
- for (domain = strchr(regtype, '.');
- domain;
- domain = strchr(domain + 1, '.'))
- if (domain[1] != '_')
- break;
-
- if (domain)
- *domain++ = '\0';
-
- fprintf(stderr,
- "DEBUG: Resolving service \"%s\", regtype \"%s\", domain \"%s\"\n",
- hostname, regtype, domain ? domain : "(null)");
-
- if (DNSServiceResolve(&ref, 0, 0, hostname, regtype, domain,
- resolve_callback,
- resolved_uri) == kDNSServiceErr_NoError)
- {
- if (DNSServiceProcessResult(ref) != kDNSServiceErr_NoError)
- uri = NULL;
- else
- uri = resolved_uri;
-
- DNSServiceRefDeallocate(ref);
- }
- else
-#endif /* HAVE_DNSSD */
-
- uri = NULL;
-
- if (!uri)
- {
- fprintf(stderr, "ERROR: Unable to resolve DNS-SD service \"%s\"!\n", uri);
- exit(CUPS_BACKEND_STOP);
- }
- }
-
- return (uri);
-}
-
-
-#ifdef HAVE_DNSSD
-/*
- * 'resolve_callback()' - Build a device URI for the given service name.
- */
-
-static void
-resolve_callback(
- DNSServiceRef sdRef, /* I - Service reference */
- DNSServiceFlags flags, /* I - Results flags */
- uint32_t interfaceIndex, /* I - Interface number */
- DNSServiceErrorType errorCode, /* I - Error, if any */
- const char *fullName, /* I - Full service name */
- const char *hostTarget, /* I - Hostname */
- uint16_t port, /* I - Port number */
- uint16_t txtLen, /* I - Length of TXT record */
- const unsigned char *txtRecord, /* I - TXT record data */
- void *context) /* I - Pointer to URI buffer */
-{
- const char *scheme; /* URI scheme */
- char rp[257]; /* Remote printer */
- const void *value; /* Value from TXT record */
- uint8_t valueLen; /* Length of value */
-
-
- fprintf(stderr,
- "DEBUG2: resolve_callback(sdRef=%p, flags=%x, interfaceIndex=%u, "
- "errorCode=%d, fullName=\"%s\", hostTarget=\"%s\", port=%u, "
- "txtLen=%u, txtRecord=%p, context=%p)\n", sdRef, flags,
- interfaceIndex, errorCode, fullName, hostTarget, port, txtLen,
- txtRecord, context);
-
- /*
- * Figure out the scheme from the full name...
- */
-
- if (strstr(fullName, "._ipp"))
- scheme = "ipp";
- else if (strstr(fullName, "._printer."))
- scheme = "lpd";
- else if (strstr(fullName, "._pdl-datastream."))
- scheme = "socket";
- else
- scheme = "riousbprint";
-
- /*
- * Extract the "remote printer" key from the TXT record...
- */
-
- if ((value = TXTRecordGetValuePtr(txtLen, txtRecord, "rp",
- &valueLen)) != NULL)
- {
- /*
- * Convert to resource by concatenating with a leading "/"...
- */
-
- rp[0] = '/';
- memcpy(rp, value, valueLen);
- rp[valueLen + 1] = '\0';
- }
- else
- rp[0] = '\0';
-
- /*
- * Assemble the final device URI...
- */
-
- httpAssembleURI(HTTP_URI_CODING_ALL, (char *)context, HTTP_MAX_URI, scheme,
- NULL, hostTarget, ntohs(port), rp);
-
- fprintf(stderr, "DEBUG: Resolved URI is \"%s\"...\n", (char *)context);
-}
-#endif /* HAVE_DNSSD */
-
-
/*
* End of "$Id$".
*/