}
- /*
- * '_cupsArrayNewStrings()' - Create a new array of comma-delimited strings.
- *
- * Note: The array automatically manages copies of the strings passed. If the
- * string pointer "s" is NULL or the empty string, no strings are added to the
- * newly created array.
- */
-
- cups_array_t * /* O - Array */
- _cupsArrayNewStrings(const char *s, /* I - Delimited strings or NULL */
- char delim) /* I - Delimiter character */
+ //
+ // 'cupsArrayNewStrings()' - Create a new array of delimited strings.
+ //
+ // This function creates a new array of strings that are delimited by the
+ // specified character. The array automatically manages copies of the strings
+ // passed. If the string pointer "s" is `NULL` or the empty string, no strings
+ // are added to the newly created array.
+ //
+ // @since CUPS 2.5@
+ //
+
+ cups_array_t * // O - Array
+ cupsArrayNewStrings(const char *s, // I - Delimited strings or `NULL`
+ char delim) // I - Delimiter character
{
- cups_array_t *a; /* Array */
+ cups_array_t *a; // Array
- if ((a = cupsArrayNew3((cups_array_func_t)_cupsArrayStrcmp, NULL, NULL, 0,
- (cups_acopy_func_t)_cupsStrPrivAlloc,
- (cups_afree_func_t)_cupsStrPrivFree)) != NULL)
- _cupsArrayAddStrings(a, s, delim);
- if ((a = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, (cups_acopy_cb_t)_cupsStrAlloc, (cups_afree_cb_t)_cupsStrFree)) != NULL)
++ if ((a = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, (cups_acopy_cb_t)_cupsArrayStrdup, (cups_afree_cb_t)_cupsArrayFree)) != NULL)
+ cupsArrayAddStrings(a, s, delim);
return (a);
}
unsigned flags);
static void cups_create_constraints(cups_dinfo_t *dinfo);
static void cups_create_defaults(cups_dinfo_t *dinfo);
- static void cups_create_media_db(cups_dinfo_t *dinfo,
- unsigned flags);
+ static void cups_create_media_db(cups_dinfo_t *dinfo, unsigned flags);
-static void cups_free_media_db(_cups_media_db_t *mdb);
+static void cups_free_media_db(_cups_media_db_t *mdb, void *data);
- static int cups_get_media_db(http_t *http, cups_dinfo_t *dinfo,
- pwg_media_t *pwg, unsigned flags,
- cups_size_t *size);
+ static int cups_get_media_db(http_t *http, cups_dinfo_t *dinfo, pwg_media_t *pwg, unsigned flags, cups_size_t *size, cups_media_t *media);
static int cups_is_close_media_db(_cups_media_db_t *a,
_cups_media_db_t *b);
- static cups_array_t *cups_test_constraints(cups_dinfo_t *dinfo,
- const char *new_option,
- const char *new_value,
- int num_options,
- cups_option_t *options,
- int *num_conflicts,
- cups_option_t **conflicts);
+ static cups_array_t *cups_test_constraints(cups_dinfo_t *dinfo, const char *new_option, const char *new_value, int num_options, cups_option_t *options, int *num_conflicts, cups_option_t **conflicts);
static void cups_update_ready(http_t *http, cups_dinfo_t *dinfo);
}
- #ifdef HAVE_DNSSD
- # ifdef HAVE_MDNSRESPONDER
- /*
- * 'cups_dnssd_browse_cb()' - Browse for printers.
- */
+ //
+ // 'cups_dest_browse_cb()' - Browse for printers.
+ //
static void
- cups_dnssd_browse_cb(
- 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 - Enumeration data */
+ cups_dest_browse_cb(
+ cups_dnssd_browse_t *browse, // I - DNS-SD browser
+ void *context, // I - Enumeration data
+ cups_dnssd_flags_t flags, // I - Flags
+ uint32_t if_index, // I - Interface
+ const char *serviceName, // I - Name of service/device
+ const char *regtype, // I - Type of service
+ const char *replyDomain) // I - Service domain
{
_cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context;
- /* Enumeration data */
+ // Enumeration data
- DEBUG_printf(("5cups_dnssd_browse_cb(sdRef=%p, flags=%x, interfaceIndex=%d, errorCode=%d, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\", context=%p)", (void *)sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain, context));
+ DEBUG_printf("5cups_dest_browse_cb(browse=%p, context=%p, flags=%x, if_index=%d, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\")", (void *)browse, context, flags, if_index, serviceName, regtype, replyDomain);
- /*
- * Don't do anything on error...
- */
-
- if (errorCode != kDNSServiceErr_NoError)
+ // Don't do anything on error, only add services...
+ if ((flags & CUPS_DNSSD_FLAGS_ERROR) || !(flags & CUPS_DNSSD_FLAGS_ADD))
return;
- /*
- * Get the device...
- */
-
+ // Get the device...
cups_dnssd_get_device(data, serviceName, regtype, replyDomain);
}
- # else /* HAVE_AVAHI */
- /*
- * 'cups_dnssd_browse_cb()' - Browse for printers.
- */
-
- static void
- cups_dnssd_browse_cb(
- AvahiServiceBrowser *browser, /* I - Browser */
- AvahiIfIndex interface, /* I - Interface index (unused) */
- AvahiProtocol protocol, /* I - Network protocol (unused) */
- AvahiBrowserEvent event, /* I - What happened */
- const char *name, /* I - Service name */
- const char *type, /* I - Registration type */
- const char *domain, /* I - Domain */
- AvahiLookupResultFlags flags, /* I - Flags */
- void *context) /* I - Devices array */
- {
- #ifdef DEBUG
- AvahiClient *client = avahi_service_browser_get_client(browser);
- /* Client information */
- #endif /* DEBUG */
- _cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context;
- /* Enumeration data */
-
-
- (void)interface;
- (void)protocol;
- (void)context;
-
- DEBUG_printf(("cups_dnssd_browse_cb(..., name=\"%s\", type=\"%s\", domain=\"%s\", ...);", name, type, domain));
-
- switch (event)
- {
- case AVAHI_BROWSER_FAILURE:
- DEBUG_printf(("cups_dnssd_browse_cb: %s", avahi_strerror(avahi_client_errno(client))));
- avahi_simple_poll_quit(data->simple_poll);
- break;
-
- case AVAHI_BROWSER_NEW:
- /*
- * This object is new on the network.
- */
-
- cups_dnssd_get_device(data, name, type, domain);
- break;
-
- case AVAHI_BROWSER_REMOVE :
- case AVAHI_BROWSER_CACHE_EXHAUSTED :
- break;
-
- case AVAHI_BROWSER_ALL_FOR_NOW :
- DEBUG_puts("cups_dnssd_browse_cb: ALL_FOR_NOW");
- data->browsers --;
- break;
- }
- }
-
-
- /*
- * 'cups_dnssd_client_cb()' - Avahi client callback function.
- */
-
- static void
- cups_dnssd_client_cb(
- AvahiClient *client, /* I - Client information (unused) */
- AvahiClientState state, /* I - Current state */
- void *context) /* I - User data (unused) */
- {
- _cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context;
- /* Enumeration data */
-
-
- (void)client;
-
- DEBUG_printf(("cups_dnssd_client_cb(client=%p, state=%d, context=%p)", client, state, context));
-
- /*
- * If the connection drops, quit.
- */
-
- if (state == AVAHI_CLIENT_FAILURE)
- {
- DEBUG_puts("cups_dnssd_client_cb: Avahi connection failed.");
- avahi_simple_poll_quit(data->simple_poll);
- }
- }
- # endif /* HAVE_MDNSRESPONDER */
-
-
- /*
- * 'cups_dnssd_compare_device()' - Compare two devices.
- */
+
+
+ //
+ // 'cups_dnssd_compare_device()' - Compare two devices.
+ //
- static int /* O - Result of comparison */
- cups_dnssd_compare_devices(_cups_dnssd_device_t *a, /* I - First device */
- _cups_dnssd_device_t *b, /* I - Second device */
- void *data) /* Unused */
+ static int // O - Result of comparison
+ cups_dnssd_compare_devices(
+ _cups_dnssd_device_t *a, // I - First device
- _cups_dnssd_device_t *b) // I - Second device
++ _cups_dnssd_device_t *b, // I - Second device
++ void *data) // I - Callback data (unused)
{
+ (void)data;
return (strcmp(a->dest.name, b->dest.name));
}
*/
- #ifdef __APPLE__
- static const char *appleLangDefault(void);
- # ifdef CUPS_BUNDLEDIR
- # ifndef CF_RETURNS_RETAINED
- # if __has_feature(attribute_cf_returns_retained)
- # define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
- # else
- # define CF_RETURNS_RETAINED
- # endif /* __has_feature(attribute_cf_returns_retained) */
- # endif /* !CF_RETURNED_RETAINED */
- static cups_array_t *appleMessageLoad(const char *locale) CF_RETURNS_RETAINED;
- # endif /* CUPS_BUNDLEDIR */
- #endif /* __APPLE__ */
static cups_lang_t *cups_cache_lookup(const char *name, cups_encoding_t encoding);
-static int cups_message_compare(_cups_message_t *m1, _cups_message_t *m2);
-static void cups_message_free(_cups_message_t *m);
+static int cups_message_compare(_cups_message_t *m1, _cups_message_t *m2,
+ void *data);
+static void cups_message_free(_cups_message_t *m, void *data);
static void cups_message_load(cups_lang_t *lang);
static void cups_message_puts(cups_file_t *fp, const char *s);
static int cups_read_strings(cups_file_t *fp, int flags, cups_array_t *a);
y_dim = ippFindAttribute(media_size, "y-dimension", IPP_TAG_INTEGER);
if (x_dim && y_dim && (pwg = pwgMediaForSize(ippGetInteger(x_dim, 0), ippGetInteger(y_dim, 0))) != NULL)
- strlcpy(ppdname, pwg->ppd, sizeof(ppdname));
+ cupsCopyString(ppdname, pwg->ppd, sizeof(ppdname));
else
- strlcpy(ppdname, "Unknown", sizeof(ppdname));
+ cupsCopyString(ppdname, "Unknown", sizeof(ppdname));
}
else
- strlcpy(ppdname, "Unknown", sizeof(ppdname));
+ cupsCopyString(ppdname, "Unknown", sizeof(ppdname));
}
else if ((pwg = pwgMediaForPWG(ippGetString(ippFindAttribute(supported, "media-default", IPP_TAG_ZERO), 0, NULL))) != NULL)
- strlcpy(ppdname, pwg->ppd, sizeof(ppdname));
+ cupsCopyString(ppdname, pwg->ppd, sizeof(ppdname));
else
- strlcpy(ppdname, "Unknown", sizeof(ppdname));
+ cupsCopyString(ppdname, "Unknown", sizeof(ppdname));
- sizes = cupsArrayNew3((cups_array_func_t)pwg_compare_sizes, NULL, NULL, 0, (cups_acopy_func_t)pwg_copy_size, (cups_afree_func_t)free);
+ sizes = cupsArrayNew3((cups_array_func_t)pwg_compare_sizes, NULL, NULL, 0, (cups_acopy_func_t)pwg_copy_size, _cupsArrayFree);
if ((attr = ippFindAttribute(supported, "media-col-database", IPP_TAG_BEGIN_COLLECTION)) != NULL)
{
extern int _cups_isupper(int ch);
extern int _cups_tolower(int ch);
extern int _cups_toupper(int ch);
- # endif /* _CUPS_INLINE */
+ # endif // _CUPS_INLINE
- /*
- * Prototypes...
- */
+ //
+ // Functions...
+ //
- extern ssize_t _cups_safe_vsnprintf(char *buffer, size_t bufsize, const char *format, va_list args) _CUPS_PRIVATE;
extern void _cups_strcpy(char *dst, const char *src) _CUPS_PRIVATE;
-
- # ifndef HAVE_STRDUP
- extern char *_cups_strdup(const char *) _CUPS_PRIVATE;
- # define strdup _cups_strdup
- # endif /* !HAVE_STRDUP */
-
extern int _cups_strcasecmp(const char *, const char *) _CUPS_PRIVATE;
-
extern int _cups_strncasecmp(const char *, const char *, size_t n) _CUPS_PRIVATE;
- # ifndef HAVE_STRLCAT
- extern size_t _cups_strlcat(char *, const char *, size_t) _CUPS_PRIVATE;
- # define strlcat _cups_strlcat
- # endif /* !HAVE_STRLCAT */
-
- # ifndef HAVE_STRLCPY
- extern size_t _cups_strlcpy(char *, const char *, size_t) _CUPS_PRIVATE;
- # define strlcpy _cups_strlcpy
- # endif /* !HAVE_STRLCPY */
-
- # ifndef HAVE_SNPRINTF
- extern int _cups_snprintf(char *, size_t, const char *, ...) _CUPS_FORMAT(3, 4) _CUPS_PRIVATE;
- # define snprintf _cups_snprintf
- # endif /* !HAVE_SNPRINTF */
-
- # ifndef HAVE_VSNPRINTF
- extern int _cups_vsnprintf(char *, size_t, const char *, va_list) _CUPS_PRIVATE;
- # define vsnprintf _cups_vsnprintf
- # endif /* !HAVE_VSNPRINTF */
-
- /*
- * String pool functions...
- */
+
++extern int _cupsArrayStrcasecmp(const char *s, const char *t, void *data) _CUPS_PRIVATE;
++extern int _cupsArrayStrcmp(const char *s1, const char *s2, void *data) _CUPS_PRIVATE;
++extern char *_cupsArrayStrdup(const char *element, void *data) _CUPS_PRIVATE;
++extern void _cupsArrayFree(void *element, void *data) _CUPS_PRIVATE;
+
extern char *_cupsStrAlloc(const char *s) _CUPS_PRIVATE;
+ extern char *_cupsStrDate(char *buf, size_t bufsize, time_t timeval) _CUPS_PRIVATE;
extern void _cupsStrFlush(void) _CUPS_PRIVATE;
+ extern char *_cupsStrFormatd(char *buf, char *bufend, double number, struct lconv *loc) _CUPS_PRIVATE;
extern void _cupsStrFree(const char *s) _CUPS_PRIVATE;
extern char *_cupsStrRetain(const char *s) _CUPS_PRIVATE;
+ extern double _cupsStrScand(const char *buf, char **bufptr, struct lconv *loc) _CUPS_PRIVATE;
extern size_t _cupsStrStatistics(size_t *alloc_bytes, size_t *total_bytes) _CUPS_PRIVATE;
- extern char *_cupsStrPrivAlloc(const char *s, void *data) _CUPS_PRIVATE;
- extern void _cupsStrPrivFree(const char *s, void *data) _CUPS_PRIVATE;
-
- /*
- * Floating point number functions...
- */
-
- extern char *_cupsStrFormatd(char *buf, char *bufend, double number,
- struct lconv *loc) _CUPS_PRIVATE;
- extern double _cupsStrScand(const char *buf, char **bufptr,
- struct lconv *loc) _CUPS_PRIVATE;
-
-
- /*
- * Date function...
- */
-
- extern char *_cupsStrDate(char *buf, size_t bufsize, time_t timeval) _CUPS_PRIVATE;
-
- extern int _cupsArrayStrcmp(const char *s1, const char *s2, void *data) _CUPS_PRIVATE;
-
- extern int _cupsArrayStrcasecmp(const char *s, const char *t, void *data) _CUPS_PRIVATE;
-
- extern char *_cupsArrayStrdup(const char *element, void *data) _CUPS_PRIVATE;
-
- extern void _cupsArrayFree(void *element, void *data) _CUPS_PRIVATE;
-
- /*
- * C++ magic...
- */
# ifdef __cplusplus
}
* Local functions...
*/
-static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b);
+static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b, void *data);
+ static void validate_end(char *s, char *end);
+
+
+ //
+ // 'cupsConcatString()' - Safely concatenate two UTF-8 strings.
+ //
+ // @since CUPS 2.5@
+ //
+
+ size_t // O - Length of string
+ cupsConcatString(char *dst, // O - Destination string
+ const char *src, // I - Source string
+ size_t dstsize) // I - Size of destination string buffer
+ {
+ size_t srclen; // Length of source string
+ size_t dstlen; // Length of destination string
+
+
+ // Range check input...
+ if (!dst || !src || dstsize == 0)
+ return (0);
+
+ // Figure out how much room is left...
+ dstlen = strlen(dst);
+
+ if (dstsize < (dstlen + 1))
+ return (dstlen); // No room, return immediately...
+
+ dstsize -= dstlen + 1;
+
+ // Figure out how much room is needed...
+ srclen = strlen(src);
+
+ // Copy the appropriate amount...
+ if (srclen <= dstsize)
+ {
+ // String fits, just copy over...
+ memmove(dst + dstlen, src, srclen);
+ dst[dstlen + srclen] = '\0';
+ }
+ else
+ {
+ // String too big, copy what we can and clean up the end...
+ memmove(dst + dstlen, src, dstsize);
+ dst[dstlen + dstsize] = '\0';
+
+ validate_end(dst, dst + dstlen + dstsize);
+ }
+
+ return (dstlen + srclen);
+ }
+
+
+ //
+ // 'cupsCopyString()' - Safely copy a UTF-8 string.
+ //
+ // @since CUPS 2.5@
+ //
+
+ size_t // O - Length of string
+ cupsCopyString(char *dst, // O - Destination string
+ const char *src, // I - Source string
+ size_t dstsize) // I - Size of destination string buffer
+ {
+ size_t srclen; // Length of source string
+
+
+ // Range check input...
+ if (!dst || !src || dstsize == 0)
+ {
+ if (dst)
+ *dst = '\0';
+ return (0);
+ }
+
+ // Figure out how much room is needed...
+ dstsize --;
+
+ srclen = strlen(src);
+
+ // Copy the appropriate amount...
+ if (srclen <= dstsize)
+ {
+ // Source string will fit...
+ memmove(dst, src, srclen);
+ dst[srclen] = '\0';
+ }
+ else
+ {
+ // Source string too big, copy what we can and clean up the end...
+ memmove(dst, src, dstsize);
+ dst[dstsize] = '\0';
+
+ validate_end(dst, dst + dstsize);
+ }
+
+ return (srclen);
+ }
+
+
+ //
+ // 'cupsFormatString()' - Format a UTF-8 string into a fixed size buffer.
+ //
+ // This function formats a UTF-8 string into a fixed size buffer, escaping
+ // special/control characters as needed so they can be safely displayed or
+ // logged.
+ //
+ // @since CUPS 2.5@
+ //
+
+ ssize_t // O - Number of bytes formatted
+ cupsFormatString(
+ char *buffer, // O - Output buffer
+ size_t bufsize, // O - Size of output buffer
+ const char *format, // I - `printf`-style format string
+ ...) // I - Additional arguments
+ {
+ va_list ap; // Pointer to additional arguments
+ ssize_t ret; // Return value
+
+
+ // Range check input...
+ if (!buffer || bufsize < 2 || !format)
+ return (-1);
+
+ // Format the string...
+ va_start(ap, format);
+ ret = cupsFormatStringv(buffer, bufsize, format, ap);
+ va_end(ap);
+
+ // Return the number of bytes that could have been written...
+ return (ret);
+ }
+
+
+ //
+ // 'cupsFormatStringv()' - Format a UTF-8 string into a fixed size buffer (`va_list` version).
+ //
+ // This function formats a UTF-8 string into a fixed size buffer using a
+ // variable argument pointer, escaping special/control characters as needed so
+ // they can be safely displayed or logged.
+ //
+ // @since CUPS 2.5@
+ //
+
+ ssize_t // O - Number of bytes formatted
+ cupsFormatStringv(
+ 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
+ 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 snprintf()
+ *tptr, // Pointer into temporary format
+ temp[1024]; // Buffer for formatted numbers
+ char *s; // Pointer to string
+ ssize_t bytes; // Total number of bytes needed
+
+
+ // Range check input...
+ if (!buffer || bufsize < 2 || !format)
+ return (-1);
+
+ // Loop through the format string, formatting as needed...
+ bufptr = buffer;
+ bufend = buffer + bufsize - 1;
+ bytes = 0;
+
+ while (*format)
+ {
+ if (*format == '%')
+ {
+ // Format character...
+ tptr = tformat;
+ *tptr++ = *format++;
+
+ if (*format == '%')
+ {
+ if (bufptr < bufend)
+ *bufptr++ = *format;
+ bytes ++;
+ format ++;
+ continue;
+ }
+ else if (strchr(" -+#\'", *format))
+ {
+ *tptr++ = *format++;
+ }
+
+ if (*format == '*')
+ {
+ // Get width from argument...
+ format ++;
+ width = va_arg(ap, int);
+
+ snprintf(tptr, sizeof(tformat) - (size_t)(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) - (size_t)(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';
+ }
+ }
+ }
+
+ 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++;
+ }
+ else
+ {
+ size = 0;
+ }
+
+ 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 ((size_t)(width + 2) > sizeof(temp))
+ break;
+
+ snprintf(temp, sizeof(temp), tformat, va_arg(ap, double));
+
+ bytes += (int)strlen(temp);
+
+ if (bufptr < bufend)
+ {
+ cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr += strlen(bufptr);
+ }
+ break;
+
+ case 'B' : // Integer formats
+ case 'X' :
+ case 'b' :
+ case 'd' :
+ case 'i' :
+ case 'o' :
+ case 'u' :
+ case 'x' :
+ if ((size_t)(width + 2) > sizeof(temp))
+ break;
+
+ # ifdef HAVE_LONG_LONG
+ if (size == 'L')
+ snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long));
+ else
+ # endif // HAVE_LONG_LONG
+ if (size == 'l')
+ snprintf(temp, sizeof(temp), tformat, va_arg(ap, long));
+ else
+ snprintf(temp, sizeof(temp), tformat, va_arg(ap, int));
+
+ bytes += (int)strlen(temp);
+
+ if (bufptr < bufend)
+ {
+ cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr += strlen(bufptr);
+ }
+ break;
+
+ case 'p' : // Pointer value
+ if ((size_t)(width + 2) > sizeof(temp))
+ break;
+
+ snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *));
+
+ bytes += (int)strlen(temp);
+
+ if (bufptr < bufend)
+ {
+ cupsCopyString(bufptr, temp, (size_t)(bufend - bufptr));
+ bufptr += strlen(bufptr);
+ }
+ break;
+
+ case 'c' : // Character or character array
+ bytes += width;
+
+ if (bufptr < bufend)
+ {
+ if (width <= 1)
+ {
+ *bufptr++ = (char)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 (; *s && bufptr < bufend; s ++)
+ {
+ if (*s == '\n')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = 'n';
+ bytes += 2;
+ }
+ else if (*s == '\r')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = 'r';
+ bytes += 2;
+ }
+ else if (*s == '\t')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = 't';
+ bytes += 2;
+ }
+ else if (*s == '\\')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = '\\';
+ bytes += 2;
+ }
+ else if (*s == '\'')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = '\'';
+ bytes += 2;
+ }
+ else if (*s == '\"')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = '\"';
+ bytes += 2;
+ }
+ else if ((*s & 255) < ' ')
+ {
+ *bufptr++ = '\\';
+ if (bufptr < bufend)
+ *bufptr++ = '0';
+ if (bufptr < bufend)
+ *bufptr++ = '0' + *s / 8;
+ if (bufptr < bufend)
+ *bufptr++ = '0' + (*s & 7);
+ bytes += 4;
+ }
+ else
+ {
+ *bufptr++ = *s;
+ bytes ++;
+ }
+ }
+
+ if (bufptr >= bufend)
+ bytes += 2 * strlen(s);
+ break;
+
+ case 'n' : // Output number of chars so far
+ *(va_arg(ap, int *)) = (int)bytes;
+ break;
+ }
+ }
+ else
+ {
+ // Literal character...
+ bytes ++;
+
+ if (bufptr < bufend)
+ *bufptr++ = *format++;
+ }
+ }
+
+ // Nul-terminate the string and return the number of characters needed.
+ if (bufptr < bufend)
+ {
+ // Everything fit in the buffer...
+ *bufptr = '\0';
+ }
+ else
+ {
+ // Make sure the last characters are valid UTF-8...
+ *bufend = '\0';
+
+ validate_end(buffer, bufend);
+ }
+
+ return (bytes);
+ }
+
/*
* '_cupsStrAlloc()' - Allocate/reference a string.
_cups_strcasecmp(const char *s, /* I - First string */
const char *t) /* I - Second string */
{
- char u, v;
++ int diff;
++
++
while (*s != '\0' && *t != '\0')
{
- u = _cups_tolower(*s);
- v = _cups_tolower(*t);
- if (_cups_tolower(*s) < _cups_tolower(*t))
++ diff = _cups_tolower(*s) - _cups_tolower(*t);
+
- if (u < v)
++ if (diff < 0)
return (-1);
- else if (u > v)
- else if (_cups_tolower(*s) > _cups_tolower(*t))
++ else if (diff > 0)
return (1);
s ++;
const char *t, /* I - Second string */
size_t n) /* I - Maximum number of characters to compare */
{
- char u, v;
++ int diff;
++
++
while (*s != '\0' && *t != '\0' && n > 0)
{
- u = _cups_tolower(*s);
- v = _cups_tolower(*t);
- if (u < v)
- if (_cups_tolower(*s) < _cups_tolower(*t))
++ diff = _cups_tolower(*s) - _cups_tolower(*t);
++ if (diff < 0)
return (-1);
- else if (u > v)
- else if (_cups_tolower(*s) > _cups_tolower(*t))
++ else if (diff > 0)
return (1);
s ++;
}
- #ifndef HAVE_STRLCAT
/*
- * '_cups_strlcat()' - Safely concatenate two strings.
+ * 'compare_sp_items()' - Compare two string pool items...
*/
- size_t /* O - Length of string */
- _cups_strlcat(char *dst, /* O - Destination string */
- const char *src, /* I - Source string */
- size_t size) /* I - Size of destination string buffer */
+ static int /* O - Result of comparison */
+ compare_sp_items(_cups_sp_item_t *a, /* I - First item */
- _cups_sp_item_t *b) /* I - Second item */
++ _cups_sp_item_t *b, /* I - Second item */
++ void *data) /* I - Unused */
{
- size_t srclen; /* Length of source string */
- size_t dstlen; /* Length of destination string */
-
-
- /*
- * Figure out how much room is left...
- */
-
- dstlen = strlen(dst);
-
- if (size < (dstlen + 1))
- return (dstlen); /* No room, return immediately... */
-
- size -= dstlen + 1;
-
- /*
- * Figure out how much room is needed...
- */
-
- srclen = strlen(src);
-
- /*
- * Copy the appropriate amount...
- */
-
- if (srclen > size)
- srclen = size;
-
- memmove(dst + dstlen, src, srclen);
- dst[dstlen + srclen] = '\0';
-
- return (dstlen + srclen);
- return (strcmp(a->str, b->str));
++ (void)data;
++
++ return (strcmp(a->str, b->str));
}
- #endif /* !HAVE_STRLCAT */
- #ifndef HAVE_STRLCPY
- /*
- * '_cups_strlcpy()' - Safely copy two strings.
- */
+ //
+ // 'validate_end()' - Validate the last UTF-8 character in a buffer.
+ //
- size_t /* O - Length of string */
- _cups_strlcpy(char *dst, /* O - Destination string */
- const char *src, /* I - Source string */
- size_t size) /* I - Size of destination string buffer */
+ static void
+ validate_end(char *s, // I - Pointer to start of string
+ char *end) // I - Pointer to end of string
{
- size_t srclen; /* Length of source string */
+ char *ptr = end - 1; // Pointer into string
- if (size == 0)
- return (0);
-
- /*
- * Figure out how much room is needed...
- */
-
- size --;
-
- srclen = strlen(src);
-
- /*
- * Copy the appropriate amount...
- */
-
- if (srclen > size)
- srclen = size;
-
- memmove(dst, src, srclen);
- dst[srclen] = '\0';
-
- return (srclen);
- }
- #endif /* !HAVE_STRLCPY */
-
-
- /*
- * 'compare_sp_items()' - Compare two string pool items...
- */
+ if (ptr > s && *ptr & 0x80)
+ {
+ while ((*ptr & 0xc0) == 0x80 && ptr > s)
+ ptr --;
- static int /* O - Result of comparison */
- compare_sp_items(_cups_sp_item_t *a, /* I - First item */
- _cups_sp_item_t *b, /* I - Second item */
- void *data) /* Unused */
- {
- (void)data;
- return (strcmp(a->str, b->str));
+ if ((*ptr & 0xe0) == 0xc0)
+ {
+ // Verify 2-byte UTF-8 sequence...
+ if ((end - ptr) != 2)
+ *ptr = '\0';
+ }
+ else if ((*ptr & 0xf0) == 0xe0)
+ {
+ // Verify 3-byte UTF-8 sequence...
+ if ((end - ptr) != 3)
+ *ptr = '\0';
+ }
+ else if ((*ptr & 0xf8) == 0xf0)
+ {
+ // Verify 4-byte UTF-8 sequence...
+ if ((end - ptr) != 4)
+ *ptr = '\0';
+ }
+ else if (*ptr & 0x80)
+ {
+ // Invalid sequence at end...
+ *ptr = '\0';
+ }
+ }
}
- int _cupsArrayStrcasecmp(const char *s, /* I - First string */
+
+
+/*
+ * '_cupsArrayStrcasecmp()' - Compare two strings...
+ */
+
- void *data) /* Unused */
++int /* O - Result of comparison */
++_cupsArrayStrcasecmp(const char *s, /* I - First string */
+ const char *t, /* I - Second string */
- return _cups_strcasecmp(s, t);
++ void *data) /* I - Unused */
+{
+ (void)data;
++ return (_cups_strcasecmp(s, t));
+}
static int load_words(const char *filename, cups_array_t *array);
- /*
- * 'main()' - Main entry.
- */
+ //
+ // 'main()' - Main entry.
+ //
- int /* O - Exit status */
+ int // O - Exit status
main(void)
{
- int i; /* Looping var */
- cups_array_t *array, /* Test array */
- *dup_array; /* Duplicate array */
- int status; /* Exit status */
- char *text; /* Text from array */
- char word[256]; /* Word from file */
- double start, /* Start time */
- end; /* End time */
- cups_dir_t *dir; /* Current directory */
- cups_dentry_t *dent; /* Directory entry */
- char *saved[32]; /* Saved entries */
- void *data; /* User data for arrays */
-
-
- /*
- * No errors so far...
- */
-
+ int i; // Looping var
+ cups_array_t *array, // Test array
+ *dup_array; // Duplicate array
+ int status; // Exit status
+ char *text; // Text from array
+ char word[256]; // Word from file
+ double start, // Start time
+ end; // End time
+ cups_dir_t *dir; // Current directory
+ cups_dentry_t *dent; // Directory entry
+ char *saved[32]; // Saved entries
+ void *data; // User data for arrays
+
+
+ // No errors so far...
status = 0;
- /*
- * cupsArrayNew()
- */
-
- fputs("cupsArrayNew: ", stdout);
+ // cupsArrayNew()
+ testBegin("cupsArrayNew3");
data = (void *)"testarray";
- array = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, data);
- array = cupsArrayNew3((cups_array_cb_t)strcmp, data, NULL, 0, (cups_acopy_cb_t)strdup, (cups_afree_cb_t)free);
++ array = cupsArrayNew3((cups_array_func_t)_cupsArrayStrcmp, data, NULL, 0, (cups_acopy_cb_t)_cupsArrayStrdup, (cups_afree_cb_t)_cupsArrayFree);
if (array)
- puts("PASS");
+ {
+ testEnd(true);
+ }
else
{
- puts("FAIL (returned NULL, expected pointer)");
+ testEndMessage(false, "returned NULL, expected pointer");
status ++;
}
static int check_if_modified(cupsd_client_t *con,
struct stat *filestats);
--static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
- void *data);
- #ifdef HAVE_TLS
- void *data);
++static int compare_clients(cupsd_client_t *a, cupsd_client_t *b, void *data);
static int cupsd_start_tls(cupsd_client_t *con, http_encryption_t e);
- #endif /* HAVE_TLS */
static char *get_file(cupsd_client_t *con, struct stat *filestats,
- char *filename, size_t len);
+ char *filename, size_t len);
static http_status_t install_cupsd_conf(cupsd_client_t *con);
static int is_cgi(cupsd_client_t *con, const char *filename,
- struct stat *filestats, mime_type_t *type);
+ struct stat *filestats, mime_type_t *type);
static int is_path_absolute(const char *path);
static int pipe_command(cupsd_client_t *con, int infile, int *outfile,
- char *command, char *options, int root);
+ char *command, char *options, int root);
static int valid_host(cupsd_client_t *con);
static int write_file(cupsd_client_t *con, http_status_t code,
- char *filename, char *type,
- struct stat *filestats);
+ char *filename, char *type,
+ struct stat *filestats);
static void write_pipe(cupsd_client_t *con);
static void cat_ppd(const char *name, int request_id) _CUPS_NORETURN;
static int cat_static(const char *name, int request_id);
static int cat_tar(const char *name, int request_id);
-static int compare_inodes(struct stat *a, struct stat *b);
-static int compare_matches(const ppd_info_t *p0, const ppd_info_t *p1);
-static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1);
-static int compare_ppds(const ppd_info_t *p0, const ppd_info_t *p1);
+static int compare_inodes(struct stat *a, struct stat *b, void *data);
- static int compare_matches(const ppd_info_t *p0,
- const ppd_info_t *p1,
- void *data);
- static int compare_names(const ppd_info_t *p0,
- const ppd_info_t *p1,
- void *data);
- static int compare_ppds(const ppd_info_t *p0,
- const ppd_info_t *p1,
- void *data);
++static int compare_matches(const ppd_info_t *p0, const ppd_info_t *p1, void *data);
++static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1, void *data);
++static int compare_ppds(const ppd_info_t *p0, const ppd_info_t *p1, void *data);
static void dump_ppds_dat(const char *filename) _CUPS_NORETURN;
static void free_array(cups_array_t *a);
- static cups_file_t *get_file(const char *name, int request_id,
- const char *subdir, char *buffer,
- size_t bufsize, char **subfile);
+ static cups_file_t *get_file(const char *name, int request_id, const char *subdir, char *buffer, size_t bufsize, char **subfile);
static void list_ppds(int request_id, int limit, const char *opt) _CUPS_NORETURN;
- static int load_drivers(cups_array_t *include,
- cups_array_t *exclude);
- static int load_drv(const char *filename, const char *name,
- cups_file_t *fp, time_t mtime, off_t size);
- static void load_ppd(const char *filename, const char *name,
- const char *scheme, struct stat *fileinfo,
- ppd_info_t *ppd, cups_file_t *fp, off_t end);
+ static int load_drivers(cups_array_t *include, cups_array_t *exclude);
+ static int load_drv(const char *filename, const char *name, cups_file_t *fp, time_t mtime, off_t size);
+ static void load_ppd(const char *filename, const char *name, const char *scheme, struct stat *fileinfo, ppd_info_t *ppd, cups_file_t *fp, off_t end);
static int load_ppds(const char *d, const char *p, int descend);
- static void load_ppds_dat(char *filename, size_t filesize,
- int verbose);
- static int load_tar(const char *filename, const char *name,
- cups_file_t *fp, time_t mtime, off_t size);
- static int read_tar(cups_file_t *fp, char *name, size_t namesize,
- struct stat *info);
+ static void load_ppds_dat(char *filename, size_t filesize, int verbose);
+ static int load_tar(const char *filename, const char *name, cups_file_t *fp, time_t mtime, off_t size);
+ static int read_tar(cups_file_t *fp, char *name, size_t namesize, struct stat *info);
static regex_t *regex_device_id(const char *device_id);
static regex_t *regex_string(const char *s);
}
- /*
- * 'compare_inodes()' - Compare two inodes.
- */
+ //
+ // 'compare_inodes()' - Compare two inodes.
+ //
-static int // O - Result of comparison
-compare_inodes(struct stat *a, // I - First inode
- struct stat *b) // I - Second inode
+static int /* O - Result of comparison */
+compare_inodes(struct stat *a, /* I - First inode */
+ struct stat *b, /* I - Second inode */
- void *data) /* Unused */
++ void *data) /* I - Unused */
{
+ (void)data;
+
if (a->st_dev != b->st_dev)
return (a->st_dev - b->st_dev);
else
}
- /*
- * 'compare_matches()' - Compare PPD match scores for sorting.
- */
+ //
+ // 'compare_matches()' - Compare PPD match scores for sorting.
+ //
-static int
-compare_matches(const ppd_info_t *p0, // I - First PPD
- const ppd_info_t *p1) // I - Second PPD
+static int compare_matches(const ppd_info_t *p0, /* I - First PPD */
+ const ppd_info_t *p1, /* I - Second PPD */
- void *data) /* Unused */
++ void *data) /* I - Unused */
{
+ (void)data;
+
if (p1->matches != p0->matches)
return (p1->matches - p0->matches);
else
}
- /*
- * 'compare_names()' - Compare PPD filenames for sorting.
- */
+ //
+ // 'compare_names()' - Compare PPD filenames for sorting.
+ //
-static int // O - Result of comparison
-compare_names(const ppd_info_t *p0, // I - First PPD file
- const ppd_info_t *p1) // I - Second PPD file
+static int /* O - Result of comparison */
+compare_names(const ppd_info_t *p0, /* I - First PPD file */
+ const ppd_info_t *p1, /* I - Second PPD file */
- void *data) /* Unused */
++ void *data) /* I - Unused */
{
- int diff; /* Difference between strings */
+ int diff; // Difference between strings
+ (void)data;
if ((diff = strcmp(p0->record.filename, p1->record.filename)) != 0)
return (diff);
}
- /*
- * 'compare_ppds()' - Compare PPD file make and model names for sorting.
- */
+ //
+ // 'compare_ppds()' - Compare PPD file make and model names for sorting.
+ //
-static int // O - Result of comparison
-compare_ppds(const ppd_info_t *p0, // I - First PPD file
- const ppd_info_t *p1) // I - Second PPD file
+static int /* O - Result of comparison */
+compare_ppds(const ppd_info_t *p0, /* I - First PPD file */
+ const ppd_info_t *p1, /* I - Second PPD file */
- void *data) /* Unused */
++ void *data) /* I - Unused */
{
- int diff; /* Difference between strings */
+ int diff; // Difference between strings
/*
static int cupsd_alloc_pollfds = 0,
cupsd_update_pollfds = 0;
static struct pollfd *cupsd_pollfds = NULL;
- # ifdef HAVE_EPOLL
- static int cupsd_epoll_fd = -1;
- static struct epoll_event *cupsd_epoll_events = NULL;
- # endif /* HAVE_EPOLL */
- #else /* select() */
- static fd_set cupsd_global_input,
- cupsd_global_output,
- cupsd_current_input,
- cupsd_current_output;
- #endif /* HAVE_KQUEUE */
-
-
- /*
- * Local functions...
- */
+
+
+ //
+ // Local functions...
+ //
-static int compare_fds(_cupsd_fd_t *a, _cupsd_fd_t *b);
+static int compare_fds(_cupsd_fd_t *a, _cupsd_fd_t *b, void *data);
static _cupsd_fd_t *find_fd(int fd);
#define release_fd(f) { \
(f)->use --; \
}
- /*
- * 'compare_fds()' - Compare file descriptors.
- */
+ //
+ // 'compare_fds()' - Compare file descriptors.
+ //
- static int /* O - Result of comparison */
- compare_fds(_cupsd_fd_t *a, /* I - First file descriptor */
- _cupsd_fd_t *b, /* I - Second file descriptor */
- void *data) /* Unused */
-static int // O - Result of comparison
-compare_fds(_cupsd_fd_t *a, // I - First file descriptor
- _cupsd_fd_t *b) // I - Second file descriptor
++static int // O - Result of comparison
++compare_fds(_cupsd_fd_t *a, // I - First file descriptor
++ _cupsd_fd_t *b, // I - Second file descriptor
++ void *data) // I - Unused
{
+ (void)data;
return (a->fd - b->fd);
}
static http_status_t authenticate_request(ippeve_client_t *client);
static void clean_jobs(ippeve_printer_t *printer);
- static int compare_jobs(ippeve_job_t *a, ippeve_job_t *b, void *data);
- static void copy_attributes(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group_tag, int quickcopy);
-static int compare_jobs(ippeve_job_t *a, ippeve_job_t *b);
++static int compare_jobs(ippeve_job_t *a, ippeve_job_t *b, void *data);
+ static void copy_attributes(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group_tag, bool quickcopy);
static void copy_job_attributes(ippeve_client_t *client, ippeve_job_t *job, cups_array_t *ra);
static ippeve_client_t *create_client(ippeve_printer_t *printer, int sock);
static ippeve_job_t *create_job(ippeve_client_t *client);
}
- /*
- * 'compare_jobs()' - Compare two jobs.
- */
+ //
+ // 'compare_jobs()' - Compare two jobs.
+ //
- static int /* O - Result of comparison */
- compare_jobs(ippeve_job_t *a, /* I - First job */
- ippeve_job_t *b, /* I - Second job */
- void *data) /* Unused */
-static int // O - Result of comparison
-compare_jobs(ippeve_job_t *a, // I - First job
- ippeve_job_t *b) // I - Second job
++static int // O - Result of comparison
++compare_jobs(ippeve_job_t *a, // I - First job
++ ippeve_job_t *b, // I - Second job
++ void *data) // I - Unused
{
+ (void)data;
return (b->id - a->id);
}
goto abort_job;
}
- /*
- * Return the job info...
- */
-
+ // Return the job info...
respond_ipp(client, IPP_STATUS_OK, NULL);
- ra = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- ra = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ ra = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
cupsArrayAdd(ra, "job-id");
cupsArrayAdd(ra, "job-state");
cupsArrayAdd(ra, "job-state-message");
job->state = IPP_JSTATE_ABORTED;
job->completed = time(NULL);
- ra = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- ra = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ ra = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
cupsArrayAdd(ra, "job-id");
cupsArrayAdd(ra, "job-state");
cupsArrayAdd(ra, "job-state-reasons");
job->filename = strdup(filename);
job->state = IPP_JSTATE_PENDING;
- _cupsRWUnlock(&(client->printer->rwlock));
-
- /*
- * Process the job...
- */
+ cupsRWUnlock(&(client->printer->rwlock));
+ // Process the job...
process_job(job);
- /*
- * Return the job info...
- */
-
+ // Return the job info...
respond_ipp(client, IPP_STATUS_OK, NULL);
- ra = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- ra = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ ra = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
cupsArrayAdd(ra, "job-id");
cupsArrayAdd(ra, "job-state");
cupsArrayAdd(ra, "job-state-reasons");
job->state = IPP_JSTATE_ABORTED;
job->completed = time(NULL);
- ra = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- ra = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ ra = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
cupsArrayAdd(ra, "job-id");
cupsArrayAdd(ra, "job-state");
cupsArrayAdd(ra, "job-state-reasons");
return;
}
- /*
- * Return the job info...
- */
-
+ // Return the job info...
respond_ipp(client, IPP_STATUS_OK, NULL);
- ra = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- ra = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ ra = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
cupsArrayAdd(ra, "job-id");
cupsArrayAdd(ra, "job-state");
cupsArrayAdd(ra, "job-state-message");
# include <sys/timeb.h>
#else
# include <sys/wait.h>
- #endif /* _WIN32 */
+ #endif // _WIN32
#include <regex.h>
- #ifdef HAVE_MDNSRESPONDER
- # include <dns_sd.h>
- #elif defined(HAVE_AVAHI)
- # include <avahi-client/client.h>
- # include <avahi-client/lookup.h>
- # include <avahi-common/simple-watch.h>
- # include <avahi-common/domain.h>
- # include <avahi-common/error.h>
- # include <avahi-common/malloc.h>
- # define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
- #endif /* HAVE_MDNSRESPONDER */
+ #include <cups/dnssd.h>
#ifndef _WIN32
- extern char **environ; /* Process environment variables */
- #endif /* !_WIN32 */
+ extern char **environ; // Process environment variables
+ #endif // !_WIN32
- /*
- * Structures...
- */
+ //
+ // Structures...
+ //
- typedef enum ippfind_exit_e /* Exit codes */
+ typedef enum ippfind_exit_e // Exit codes
{
- IPPFIND_EXIT_TRUE = 0, /* OK and result is true */
- IPPFIND_EXIT_FALSE, /* OK but result is false*/
- IPPFIND_EXIT_BONJOUR, /* Browse/resolve failure */
- IPPFIND_EXIT_SYNTAX, /* Bad option or syntax error */
- IPPFIND_EXIT_MEMORY /* Out of memory */
+ IPPFIND_EXIT_TRUE = 0, // OK and result is true
+ IPPFIND_EXIT_FALSE, // OK but result is false
+ IPPFIND_EXIT_BONJOUR, // Browse/resolve failure
+ IPPFIND_EXIT_SYNTAX, // Bad option or syntax error
+ IPPFIND_EXIT_MEMORY // Out of memory
} ippfind_exit_t;
- typedef enum ippfind_op_e /* Operations for expressions */
+ typedef enum ippfind_op_e // Operations for expressions
{
- /* "Evaluation" operations */
- IPPFIND_OP_NONE, /* No operation */
- IPPFIND_OP_AND, /* Logical AND of all children */
- IPPFIND_OP_OR, /* Logical OR of all children */
- IPPFIND_OP_TRUE, /* Always true */
- IPPFIND_OP_FALSE, /* Always false */
- IPPFIND_OP_IS_LOCAL, /* Is a local service */
- IPPFIND_OP_IS_REMOTE, /* Is a remote service */
- IPPFIND_OP_DOMAIN_REGEX, /* Domain matches regular expression */
- IPPFIND_OP_NAME_REGEX, /* Name matches regular expression */
- IPPFIND_OP_NAME_LITERAL, /* Name matches literal string */
- IPPFIND_OP_HOST_REGEX, /* Hostname matches regular expression */
- IPPFIND_OP_PORT_RANGE, /* Port matches range */
- IPPFIND_OP_PATH_REGEX, /* Path matches regular expression */
- IPPFIND_OP_TXT_EXISTS, /* TXT record key exists */
- IPPFIND_OP_TXT_REGEX, /* TXT record key matches regular expression */
- IPPFIND_OP_URI_REGEX, /* URI matches regular expression */
-
- /* "Output" operations */
- IPPFIND_OP_EXEC, /* Execute when true */
- IPPFIND_OP_LIST, /* List when true */
- IPPFIND_OP_PRINT_NAME, /* Print URI when true */
- IPPFIND_OP_PRINT_URI, /* Print name when true */
- IPPFIND_OP_QUIET /* No output when true */
+ // "Evaluation" operations
+ IPPFIND_OP_NONE, // No operation
+ IPPFIND_OP_AND, // Logical AND of all children
+ IPPFIND_OP_OR, // Logical OR of all children
+ IPPFIND_OP_TRUE, // Always true
+ IPPFIND_OP_FALSE, // Always false
+ IPPFIND_OP_IS_LOCAL, // Is a local service
+ IPPFIND_OP_IS_REMOTE, // Is a remote service
+ IPPFIND_OP_DOMAIN_REGEX, // Domain matches regular expression
+ IPPFIND_OP_NAME_REGEX, // Name matches regular expression
+ IPPFIND_OP_NAME_LITERAL, // Name matches literal string
+ IPPFIND_OP_HOST_REGEX, // Hostname matches regular expression
+ IPPFIND_OP_PORT_RANGE, // Port matches range
+ IPPFIND_OP_PATH_REGEX, // Path matches regular expression
+ IPPFIND_OP_TXT_EXISTS, // TXT record key exists
+ IPPFIND_OP_TXT_REGEX, // TXT record key matches regular expression
+ IPPFIND_OP_URI_REGEX, // URI matches regular expression
+
+ // "Output" operations
+ IPPFIND_OP_EXEC, // Execute when true
+ IPPFIND_OP_LIST, // List when true
+ IPPFIND_OP_PRINT_NAME, // Print URI when true
+ IPPFIND_OP_PRINT_URI, // Print name when true
+ IPPFIND_OP_QUIET // No output when true
} ippfind_op_t;
- typedef struct ippfind_expr_s /* Expression */
+ typedef struct ippfind_expr_s // Expression
{
struct ippfind_expr_s
- *prev, /* Previous expression */
- *next, /* Next expression */
- *parent, /* Parent expressions */
- *child; /* Child expressions */
- ippfind_op_t op; /* Operation code (see above) */
- int invert; /* Invert the result */
- char *name; /* TXT record key or literal name */
- regex_t re; /* Regular expression for matching */
- int range[2]; /* Port number range */
- int num_args; /* Number of arguments for exec */
- char **args; /* Arguments for exec */
+ *prev, // Previous expression
+ *next, // Next expression
+ *parent, // Parent expressions
+ *child; // Child expressions
+ ippfind_op_t op; // Operation code (see above)
+ bool invert; // Invert the result?
+ char *name; // TXT record key or literal name
+ regex_t re; // Regular expression for matching
+ int range[2]; // Port number range
+ size_t num_args; // Number of arguments for exec
+ char **args; // Arguments for exec
} ippfind_expr_t;
- typedef struct ippfind_srv_s /* Service information */
+ typedef struct ippfind_srvs_s // Services array
{
- #ifdef HAVE_MDNSRESPONDER
- DNSServiceRef ref; /* Service reference for query */
- #elif defined(HAVE_AVAHI)
- AvahiServiceResolver *ref; /* Resolver */
- #endif /* HAVE_MDNSRESPONDER */
- char *name, /* Service name */
- *domain, /* Domain name */
- *regtype, /* Registration type */
- *fullName, /* Full name */
- *host, /* Hostname */
- *resource, /* Resource path */
- *uri; /* URI */
- int num_txt; /* Number of TXT record keys */
- cups_option_t *txt; /* TXT record keys */
- int port, /* Port number */
- is_local, /* Is a local service? */
- is_processed, /* Did we process the service? */
- is_resolved; /* Got the resolve data? */
- } ippfind_srv_t;
+ cups_rwlock_t rwlock; // R/W lock
+ cups_array_t *services; // Services array
+ } ippfind_srvs_t;
+ typedef struct ippfind_srv_s // Service information
+ {
+ cups_dnssd_resolve_t *resolve; // Resolve request
+ char *name, // Service name
+ *domain, // Domain name
+ *regtype, // Registration type
+ *fullName, // Full name
+ *host, // Hostname
+ *resource, // Resource path
+ *uri; // URI
+ int num_txt; // Number of TXT record keys
+ cups_option_t *txt; // TXT record keys
+ int port; // Port number
+ bool is_local, // Is a local service?
+ is_processed, // Did we process the service?
+ is_resolved; // Got the resolve data?
+ } ippfind_srv_t;
- /*
- * Local globals...
- */
- #ifdef HAVE_MDNSRESPONDER
- static DNSServiceRef dnssd_ref; /* Master service reference */
- #elif defined(HAVE_AVAHI)
- static AvahiClient *avahi_client = NULL;/* Client information */
- static int avahi_got_data = 0; /* Got data from poll? */
- static AvahiSimplePoll *avahi_poll = NULL;
- /* Poll information */
- #endif /* HAVE_MDNSRESPONDER */
+ //
+ // Local globals...
+ //
+ static cups_dnssd_t *dnssd; // DNS-SD context
static int address_family = AF_UNSPEC;
- /* Address family for LIST */
- static int bonjour_error = 0; /* Error browsing/resolving? */
- static double bonjour_timeout = 1.0; /* Timeout in seconds */
- static int ipp_version = 20; /* IPP version for LIST */
-
-
- /*
- * Local functions...
- */
-
- #ifdef HAVE_MDNSRESPONDER
- static void DNSSD_API browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8);
- static void DNSSD_API browse_local_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) _CUPS_NONNULL(1,5,6,7,8);
- #elif defined(HAVE_AVAHI)
- static void browse_callback(AvahiServiceBrowser *browser,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiBrowserEvent event,
- const char *serviceName,
- const char *regtype,
- const char *replyDomain,
- AvahiLookupResultFlags flags,
- void *context);
- static void client_callback(AvahiClient *client,
- AvahiClientState state,
- void *context);
- #endif /* HAVE_MDNSRESPONDER */
+ // Address family for LIST
+ static int bonjour_error = 0; // Error browsing/resolving?
+ static double bonjour_timeout = 1.0; // Timeout in seconds
+ static int ipp_version = 20; // IPP version for LIST
-static int compare_services(ippfind_srv_t *a, ippfind_srv_t *b);
+
+ //
+ // Local functions...
+ //
+
+ static void browse_callback(cups_dnssd_browse_t *browse, void *context, cups_dnssd_flags_t flags, uint32_t if_index, const char *serviceName, const char *regtype, const char *replyDomain);
- static const char *dnssd_error_string(int error);
- static int eval_expr(ippfind_srv_t *service,
- ippfind_expr_t *expressions);
- static int exec_program(ippfind_srv_t *service, int num_args,
- char **args);
- static ippfind_srv_t *get_service(cups_array_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4);
+static int compare_services(ippfind_srv_t *a, ippfind_srv_t *b, void *data);
+ static int eval_expr(ippfind_srv_t *service, ippfind_expr_t *expressions);
+ static int exec_program(ippfind_srv_t *service, int num_args, char **args);
+ static ippfind_srv_t *get_service(ippfind_srvs_t *services, const char *serviceName, const char *regtype, const char *replyDomain) _CUPS_NONNULL(1,2,3,4);
static double get_time(void);
static int list_service(ippfind_srv_t *service);
- static ippfind_expr_t *new_expr(ippfind_op_t op, int invert,
- const char *value, const char *regex,
- char **args);
- #ifdef HAVE_MDNSRESPONDER
- static void DNSSD_API 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) _CUPS_NONNULL(1,5,6,9, 10);
- #elif defined(HAVE_AVAHI)
- static int poll_callback(struct pollfd *pollfds,
- unsigned int num_pollfds, int timeout,
- void *context);
- static void resolve_callback(AvahiServiceResolver *res,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiResolverEvent event,
- const char *serviceName,
- const char *regtype,
- const char *replyDomain,
- const char *host_name,
- const AvahiAddress *address,
- uint16_t port,
- AvahiStringList *txt,
- AvahiLookupResultFlags flags,
- void *context);
- #endif /* HAVE_MDNSRESPONDER */
+ static ippfind_expr_t *new_expr(ippfind_op_t op, bool invert, const char *value, const char *regex, char **args);
+ static void resolve_callback(cups_dnssd_resolve_t *resolve, void *context, cups_dnssd_flags_t flags, uint32_t if_index, const char *fullName, const char *hostTarget, uint16_t port, int num_txt, cups_option_t *txt);
static void set_service_uri(ippfind_srv_t *service);
static void show_usage(void) _CUPS_NORETURN;
static void show_version(void) _CUPS_NORETURN;
static void
browse_callback(
- AvahiServiceBrowser *browser, /* I - Browser */
- AvahiIfIndex interface, /* I - Interface index (unused) */
- AvahiProtocol protocol, /* I - Network protocol (unused) */
- AvahiBrowserEvent event, /* I - What happened */
- const char *name, /* I - Service name */
- const char *type, /* I - Registration type */
- const char *domain, /* I - Domain */
- AvahiLookupResultFlags flags, /* I - Flags */
- void *context) /* I - Services array */
+ cups_dnssd_browse_t *browse, // I - Browse request
+ void *context, // I - Services array
+ cups_dnssd_flags_t flags, // I - Flags
+ uint32_t if_index, // I - Interface
+ const char *serviceName, // I - Name of service/device
+ const char *regtype, // I - Type of service
+ const char *replyDomain) // I - Service domain
{
- AvahiClient *client = avahi_service_browser_get_client(browser);
- /* Client information */
- ippfind_srv_t *service; /* Service information */
-
-
- (void)interface;
- (void)protocol;
- (void)context;
-
- switch (event)
- {
- case AVAHI_BROWSER_FAILURE:
- fprintf(stderr, "DEBUG: browse_callback: %s\n",
- avahi_strerror(avahi_client_errno(client)));
- bonjour_error = 1;
- avahi_simple_poll_quit(avahi_poll);
- break;
-
- case AVAHI_BROWSER_NEW:
- /*
- * This object is new on the network. Create a device entry for it if
- * it doesn't yet exist.
- */
+ ippfind_srv_t *service; // Service
- service = get_service((cups_array_t *)context, name, type, domain);
-
- if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
- service->is_local = 1;
- break;
-
- case AVAHI_BROWSER_REMOVE:
- case AVAHI_BROWSER_ALL_FOR_NOW:
- case AVAHI_BROWSER_CACHE_EXHAUSTED:
- break;
- }
- }
-
-
- /*
- * 'client_callback()' - Avahi client callback function.
- */
+ if (getenv("IPPFIND_DEBUG"))
+ fprintf(stderr, "B flags=0x%04X, if_index=%u, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\"\n", flags, if_index, serviceName, regtype, replyDomain);
- static void
- client_callback(
- AvahiClient *client, /* I - Client information (unused) */
- AvahiClientState state, /* I - Current state */
- void *context) /* I - User data (unused) */
- {
- (void)client;
- (void)context;
+ (void)browse;
- /*
- * If the connection drops, quit.
- */
+ // Only process "add" data...
+ if ((flags & CUPS_DNSSD_FLAGS_ERROR) || !(flags & CUPS_DNSSD_FLAGS_ADD))
+ return;
- if (state == AVAHI_CLIENT_FAILURE)
- {
- fputs("DEBUG: Avahi connection failed.\n", stderr);
- bonjour_error = 1;
- avahi_simple_poll_quit(avahi_poll);
- }
+ // Get the device...
+ service = get_service((ippfind_srvs_t *)context, serviceName, regtype, replyDomain);
+ if (if_index == CUPS_DNSSD_IF_INDEX_LOCAL)
+ service->is_local = 1;
}
- #endif /* HAVE_AVAHI */
- /*
- * 'compare_services()' - Compare two devices.
- */
+ //
+ // 'compare_services()' - Compare two devices.
+ //
- static int /* O - Result of comparison */
- compare_services(ippfind_srv_t *a, /* I - First device */
- ippfind_srv_t *b, /* I - Second device */
- void *data) /* Unused */
+ static int // O - Result of comparison
+ compare_services(ippfind_srv_t *a, // I - First device
- ippfind_srv_t *b) // I - Second device
++ ippfind_srv_t *b, // I - Second device
++ void *data) // I - Callback data (unused)
{
- return (strcmp(a->name, b->name));
- }
-
-
- /*
- * 'dnssd_error_string()' - Return an error string for an error code.
- */
-
- static const char * /* O - Error message */
- dnssd_error_string(int error) /* I - Error number */
- {
- # ifdef HAVE_MDNSRESPONDER
- switch (error)
- {
- case kDNSServiceErr_NoError :
- return ("OK.");
-
- default :
- case kDNSServiceErr_Unknown :
- return ("Unknown error.");
-
- case kDNSServiceErr_NoSuchName :
- return ("Service not found.");
-
- case kDNSServiceErr_NoMemory :
- return ("Out of memory.");
-
- case kDNSServiceErr_BadParam :
- return ("Bad parameter.");
-
- case kDNSServiceErr_BadReference :
- return ("Bad service reference.");
-
- case kDNSServiceErr_BadState :
- return ("Bad state.");
-
- case kDNSServiceErr_BadFlags :
- return ("Bad flags.");
-
- case kDNSServiceErr_Unsupported :
- return ("Unsupported.");
-
- case kDNSServiceErr_NotInitialized :
- return ("Not initialized.");
-
- case kDNSServiceErr_AlreadyRegistered :
- return ("Already registered.");
+ (void)data;
- case kDNSServiceErr_NameConflict :
- return ("Name conflict.");
-
- case kDNSServiceErr_Invalid :
- return ("Invalid name.");
-
- case kDNSServiceErr_Firewall :
- return ("Firewall prevents registration.");
-
- case kDNSServiceErr_Incompatible :
- return ("Client library incompatible.");
-
- case kDNSServiceErr_BadInterfaceIndex :
- return ("Bad interface index.");
-
- case kDNSServiceErr_Refused :
- return ("Server prevents registration.");
-
- case kDNSServiceErr_NoSuchRecord :
- return ("Record not found.");
-
- case kDNSServiceErr_NoAuth :
- return ("Authentication required.");
-
- case kDNSServiceErr_NoSuchKey :
- return ("Encryption key not found.");
-
- case kDNSServiceErr_NATTraversal :
- return ("Unable to traverse NAT boundary.");
-
- case kDNSServiceErr_DoubleNAT :
- return ("Unable to traverse double-NAT boundary.");
-
- case kDNSServiceErr_BadTime :
- return ("Bad system time.");
-
- case kDNSServiceErr_BadSig :
- return ("Bad signature.");
-
- case kDNSServiceErr_BadKey :
- return ("Bad encryption key.");
-
- case kDNSServiceErr_Transient :
- return ("Transient error occurred - please try again.");
-
- case kDNSServiceErr_ServiceNotRunning :
- return ("Server not running.");
-
- case kDNSServiceErr_NATPortMappingUnsupported :
- return ("NAT doesn't support NAT-PMP or UPnP.");
-
- case kDNSServiceErr_NATPortMappingDisabled :
- return ("NAT supports NAT-PNP or UPnP but it is disabled.");
-
- case kDNSServiceErr_NoRouter :
- return ("No Internet/default router configured.");
-
- case kDNSServiceErr_PollingMode :
- return ("Service polling mode error.");
-
- #ifndef _WIN32
- case kDNSServiceErr_Timeout :
- return ("Service timeout.");
- #endif /* !_WIN32 */
- }
-
- # elif defined(HAVE_AVAHI)
- return (avahi_strerror(error));
- # endif /* HAVE_MDNSRESPONDER */
+
+ return (_cups_strcasecmp(a->name, b->name));
}
if (ippGetGroupTag(attrptr) != IPP_TAG_OPERATION)
add_stringf(data->errors, "detailed-status-message (text(MAX)) has wrong group tag %s (RFC 8011 section 4.1.6.3).", ippTagString(ippGetGroupTag(attrptr)));
if (ippGetCount(attrptr) != 1)
- add_stringf(data->errors, "detailed-status-message (text(MAX)) has %d values (RFC 8011 section 4.1.6.3).", ippGetCount(attrptr));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has %u values (RFC 8011 section 4.1.6.3).", (unsigned)ippGetCount(attrptr));
if (detailed_status_message && strlen(detailed_status_message) > 1023)
- add_stringf(data->errors, "detailed-status-message (text(MAX)) has bad length %d (RFC 8011 section 4.1.6.3).", (int)strlen(detailed_status_message));
+ add_stringf(data->errors, "detailed-status-message (text(MAX)) has bad length %u (RFC 8011 section 4.1.6.3).", (unsigned)strlen(detailed_status_message));
}
- a = cupsArrayNew((cups_array_func_t)_cupsArrayStrcmp, NULL);
- a = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, NULL, NULL);
++ a = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, NULL, NULL);
- for (attrptr = ippFirstAttribute(response), group = ippGetGroupTag(attrptr);
+ for (attrptr = ippGetFirstAttribute(response), group = ippGetGroupTag(attrptr);
attrptr;
- attrptr = ippNextAttribute(response))
+ attrptr = ippGetNextAttribute(response))
{
if (ippGetGroupTag(attrptr) != group)
{
}
// Collect values and determine they are all unique...
- values = cupsArrayNew3((cups_array_func_t)_cupsArrayStrcmp, NULL, NULL, 0, (cups_acopy_func_t)_cupsArrayStrdup, _cupsArrayFree);
- values = cupsArrayNew3((cups_array_cb_t)strcmp, NULL, NULL, 0, (cups_acopy_cb_t)strdup, (cups_afree_cb_t)free);
++ values = cupsArrayNew3((cups_array_cb_t)_cupsArrayStrcmp, NULL, NULL, 0, (cups_acopy_cb_t)strdup, (cups_afree_cb_t)free);
for (i = 0; i < count; i ++)
{