/*
- * "$Id$"
+ * Utility to find IPP printers via Bonjour/DNS-SD and optionally run
+ * commands such as IPP and Bonjour conformance tests. This tool is
+ * inspired by the UNIX "find" command, thus its name.
*
- * Utility to find IPP printers via Bonjour/DNS-SD and optionally run
- * commands such as IPP and Bonjour conformance tests. This tool is
- * inspired by the UNIX "find" command, thus its name.
- *
- * Copyright 2008-2013 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:
+ * Copyright © 2008-2018 by Apple Inc.
*
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
* Include necessary headers.
*/
+#define _CUPS_NO_DEPRECATED
#include <cups/cups-private.h>
+#ifdef WIN32
+# include <process.h>
+# include <sys/timeb.h>
+#else
+# include <sys/wait.h>
+#endif /* WIN32 */
#include <regex.h>
#ifdef HAVE_DNSSD
# include <dns_sd.h>
# define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
#endif /* HAVE_DNSSD */
+#ifndef WIN32
+extern char **environ; /* Process environment variables */
+#endif /* !WIN32 */
+
/*
* Structures...
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_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_QUIET /* No output when true */
} ippfind_op_t;
typedef struct ippfind_expr_s /* Expression */
*child; /* Child expressions */
ippfind_op_t op; /* Operation code (see above) */
int invert; /* Invert the result */
- char *key; /* TXT record key */
+ 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 */
*/
#ifdef HAVE_DNSSD
-static void browse_callback(DNSServiceRef sdRef,
+static void DNSSD_API browse_callback(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char *regtype,
const char *replyDomain, void *context)
__attribute__((nonnull(1,5,6,7,8)));
-static void browse_local_callback(DNSServiceRef sdRef,
+static void DNSSD_API browse_local_callback(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char *value, const char *regex,
char **args);
#ifdef HAVE_DNSSD
-static void resolve_callback(DNSServiceRef sdRef,
+static void DNSSD_API resolve_callback(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
static void resolve_callback(AvahiServiceResolver *res,
AvahiIfIndex interface,
AvahiProtocol protocol,
- AvahiBrowserEvent event,
+ 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,
{
int i, /* Looping var */
have_output = 0,/* Have output expression */
- status = IPPFIND_EXIT_TRUE;
+ status = IPPFIND_EXIT_FALSE;
/* Exit status */
const char *opt, /* Option character */
*search; /* Current browse/resolve string */
/* Expression tree */
*temp = NULL, /* New expression */
*parent = NULL, /* Parent expression */
- *current = NULL;/* Current expression */
+ *current = NULL,/* Current expression */
+ *parens[100]; /* Markers for parenthesis */
+ int num_parens = 0; /* Number of parenthesis */
ippfind_op_t logic = IPPFIND_OP_AND;
/* Logic for next expression */
int invert = 0; /* Invert expression? */
struct timeval stimeout; /* Timeout for select() */
#endif /* HAVE_DNSSD */
double endtime; /* End time */
+ static const char * const ops[] = /* Node operation names */
+ {
+ "NONE",
+ "AND",
+ "OR",
+ "TRUE",
+ "FALSE",
+ "IS_LOCAL",
+ "IS_REMOTE",
+ "DOMAIN_REGEX",
+ "NAME_REGEX",
+ "NAME_LITERAL",
+ "HOST_REGEX",
+ "PORT_RANGE",
+ "PATH_REGEX",
+ "TXT_EXISTS",
+ "TXT_REGEX",
+ "URI_REGEX",
+ "EXEC",
+ "LIST",
+ "PRINT_NAME",
+ "PRINT_URI",
+ "QUIET"
+ };
/*
* Parse command-line...
*/
+ if (getenv("IPPFIND_DEBUG"))
+ for (i = 1; i < argc; i ++)
+ fprintf(stderr, "argv[%d]=\"%s\"\n", i, argv[i]);
+
for (i = 1; i < argc; i ++)
{
if (argv[i][0] == '-')
if (!strcmp(argv[i], "--and"))
{
- if (logic != IPPFIND_OP_AND && current && current->prev)
- {
- /*
- * OK, we have more than 1 rule in the current tree level.
- * Make a new group tree and move the previous rule to it...
- */
-
- if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL, NULL)) == NULL)
- return (IPPFIND_EXIT_MEMORY);
-
- temp->child = current;
- temp->parent = current->parent;
- current->prev->next = temp;
- temp->prev = current->prev;
+ if (logic == IPPFIND_OP_OR)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Cannot use --and after --or."));
+ show_usage();
+ }
- current->prev = NULL;
- current->parent = temp;
- parent = temp;
- }
- else if (parent)
- parent->op = IPPFIND_OP_AND;
+ if (!current)
+ {
+ _cupsLangPuts(stderr,
+ _("ippfind: Missing expression before \"--and\"."));
+ show_usage();
+ }
- logic = IPPFIND_OP_AND;
- temp = NULL;
+ temp = NULL;
}
else if (!strcmp(argv[i], "--domain"))
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ "--domain");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_DOMAIN_REGEX, invert, NULL, argv[i],
NULL)) == NULL)
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Expected program after %s."),
+ "--exec");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_EXEC, invert, NULL, NULL,
argv + i)) == NULL)
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Expected semi-colon after %s."),
+ "--exec");
show_usage();
+ }
have_output = 1;
}
else if (!strcmp(argv[i], "--false"))
{
- i ++;
- if (i >= argc)
- show_usage();
-
if ((temp = new_expr(IPPFIND_OP_FALSE, invert, NULL, NULL,
NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ "--host");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_HOST_REGEX, invert, NULL, argv[i],
NULL)) == NULL)
}
else if (!strcmp(argv[i], "--ls"))
{
- i ++;
- if (i >= argc)
- show_usage();
-
if ((temp = new_expr(IPPFIND_OP_LIST, invert, NULL, NULL,
NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
have_output = 1;
}
else if (!strcmp(argv[i], "--local"))
+ {
+ if ((temp = new_expr(IPPFIND_OP_IS_LOCAL, invert, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+ }
+ else if (!strcmp(argv[i], "--literal-name"))
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Missing name after %s."), "--literal-name");
show_usage();
+ }
- if ((temp = new_expr(IPPFIND_OP_IS_LOCAL, invert, NULL, NULL,
- NULL)) == NULL)
+ if ((temp = new_expr(IPPFIND_OP_NAME_LITERAL, invert, argv[i], NULL, NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
}
else if (!strcmp(argv[i], "--name"))
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ "--name");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_NAME_REGEX, invert, NULL, argv[i],
NULL)) == NULL)
}
else if (!strcmp(argv[i], "--or"))
{
- if (logic != IPPFIND_OP_OR && current)
+ if (!current)
+ {
+ _cupsLangPuts(stderr,
+ _("ippfind: Missing expression before \"--or\"."));
+ show_usage();
+ }
+
+ logic = IPPFIND_OP_OR;
+
+ if (parent && parent->op == IPPFIND_OP_OR)
+ {
+ /*
+ * Already setup to do "foo --or bar --or baz"...
+ */
+
+ temp = NULL;
+ }
+ else if (!current->prev && parent)
+ {
+ /*
+ * Change parent node into an OR node...
+ */
+
+ parent->op = IPPFIND_OP_OR;
+ temp = NULL;
+ }
+ else if (!current->prev)
+ {
+ /*
+ * Need to group "current" in a new OR node...
+ */
+
+ if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ temp->parent = parent;
+ temp->child = current;
+ current->parent = temp;
+
+ if (parent)
+ parent->child = temp;
+ else
+ expressions = temp;
+
+ parent = temp;
+ temp = NULL;
+ }
+ else
{
/*
- * OK, we have two possibilities; either this is the top-level
- * rule or we have a bunch of AND rules at this level.
+ * Need to group previous expressions in an AND node, and then
+ * put that in an OR node...
*/
- if (!parent)
+ if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ while (current->prev)
{
- /*
- * This is the top-level rule; we have to group *all* of the AND
- * rules down a level, as AND has precedence over OR.
- */
+ current->parent = temp;
+ current = current->prev;
+ }
- if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
- NULL)) == NULL)
- return (IPPFIND_EXIT_MEMORY);
+ current->parent = temp;
+ temp->child = current;
+ current = temp;
- while (current->prev)
- {
- current->parent = temp;
- current = current->prev;
- }
+ if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
- current->parent = temp;
- temp->child = current;
+ temp->parent = parent;
+ current->parent = temp;
- expressions = current = temp;
- }
- else
- {
- /*
- * This isn't the top rule, so go up one level...
- */
+ if (parent)
+ parent->child = temp;
+ else
+ expressions = temp;
- current = parent;
- parent = current->parent;
- }
+ parent = temp;
+ temp = NULL;
}
-
- logic = IPPFIND_OP_OR;
- temp = NULL;
}
else if (!strcmp(argv[i], "--path"))
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ "--path");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_PATH_REGEX, invert, NULL, argv[i],
NULL)) == NULL)
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Expected port range after %s."),
+ "--port");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_PORT_RANGE, invert, argv[i], NULL,
NULL)) == NULL)
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Expected key name after %s."),
+ "--txt");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_TXT_EXISTS, invert, argv[i], NULL,
NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
}
- else if (!strncmp(argv[i], "--txt-", 5))
+ else if (!strncmp(argv[i], "--txt-", 6))
{
- const char *key = argv[i] + 5;/* TXT key */
+ const char *key = argv[i] + 6;/* TXT key */
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ argv[i - 1]);
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_TXT_REGEX, invert, key, argv[i],
NULL)) == NULL)
{
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after %s."),
+ "--uri");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_URI_REGEX, invert, NULL, argv[i],
NULL)) == NULL)
* Add new expression...
*/
+ if (logic == IPPFIND_OP_AND &&
+ current && current->prev &&
+ parent && parent->op != IPPFIND_OP_AND)
+ {
+ /*
+ * Need to re-group "current" in a new AND node...
+ */
+
+ ippfind_expr_t *tempand; /* Temporary AND node */
+
+ if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ /*
+ * Replace "current" with new AND node at the end of this list...
+ */
+
+ current->prev->next = tempand;
+ tempand->prev = current->prev;
+ tempand->parent = parent;
+
+ /*
+ * Add "current to the new AND node...
+ */
+
+ tempand->child = current;
+ current->parent = tempand;
+ current->prev = NULL;
+ parent = tempand;
+ }
+
+ /*
+ * Add the new node at current level...
+ */
+
+ temp->parent = parent;
+ temp->prev = current;
+
if (current)
- {
- temp->parent = parent;
current->next = temp;
- }
else if (parent)
parent->child = temp;
else
expressions = temp;
- temp->prev = current;
- current = temp;
- invert = 0;
- temp = NULL;
+ current = temp;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
+ temp = NULL;
}
}
else
address_family = AF_INET6;
break;
+ case 'N' : /* Literal name */
+ i ++;
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Missing name after %s."), "-N");
+ show_usage();
+ }
+
+ if ((temp = new_expr(IPPFIND_OP_NAME_LITERAL, invert, argv[i], NULL, NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+ break;
+
case 'P' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Expected port range after %s."),
+ "-P");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_PORT_RANGE, invert, argv[i],
NULL, NULL)) == NULL)
case 'T' :
i ++;
if (i >= argc)
- show_usage();
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Missing timeout for \"-T\"."),
+ "ippfind");
+ show_usage();
+ }
bonjour_timeout = atof(argv[i]);
break;
case 'V' :
i ++;
if (i >= argc)
- show_usage();
+ {
+ _cupsLangPrintf(stderr,
+ _("%s: Missing version for \"-V\"."),
+ "ippfind");
+ show_usage();
+ }
if (!strcmp(argv[i], "1.1"))
ipp_version = 11;
else if (!strcmp(argv[i], "2.2"))
ipp_version = 22;
else
+ {
+ _cupsLangPrintf(stderr, _("%s: Bad version %s for \"-V\"."),
+ "ippfind", argv[i]);
show_usage();
+ }
break;
case 'd' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after "
+ "%s."), "-d");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_DOMAIN_REGEX, invert, NULL,
argv[i], NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
break;
- case 'e' :
- i ++;
- if (i >= argc)
- show_usage();
-
- if ((temp = new_expr(IPPFIND_OP_EXEC, invert, NULL, NULL,
- argv + i)) == NULL)
- return (IPPFIND_EXIT_MEMORY);
-
- while (i < argc)
- if (!strcmp(argv[i], ";"))
- break;
- else
- i ++;
-
- if (i >= argc)
- show_usage();
-
- have_output = 1;
- break;
-
case 'h' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after "
+ "%s."), "-h");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_HOST_REGEX, invert, NULL,
argv[i], NULL)) == NULL)
break;
case 'l' :
- i ++;
- if (i >= argc)
- show_usage();
-
if ((temp = new_expr(IPPFIND_OP_LIST, invert, NULL, NULL,
NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
case 'n' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after "
+ "%s."), "-n");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_NAME_REGEX, invert, NULL,
argv[i], NULL)) == NULL)
case 't' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing key name after %s."),
+ "-t");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_TXT_EXISTS, invert, argv[i],
NULL, NULL)) == NULL)
case 'u' :
i ++;
if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing regular expression after "
+ "%s."), "-u");
show_usage();
+ }
if ((temp = new_expr(IPPFIND_OP_URI_REGEX, invert, NULL,
argv[i], NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
break;
+ case 'x' :
+ i ++;
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing program after %s."),
+ "-x");
+ show_usage();
+ }
+
+ if ((temp = new_expr(IPPFIND_OP_EXEC, invert, NULL, NULL,
+ argv + i)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ while (i < argc)
+ if (!strcmp(argv[i], ";"))
+ break;
+ else
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPrintf(stderr,
+ _("ippfind: Missing semi-colon after %s."),
+ "-x");
+ show_usage();
+ }
+
+ have_output = 1;
+ break;
+
default :
_cupsLangPrintf(stderr, _("%s: Unknown option \"-%c\"."),
"ippfind", *opt);
show_usage();
- break;
}
if (temp)
* Add new expression...
*/
- if (current)
+ if (logic == IPPFIND_OP_AND &&
+ current && current->prev &&
+ parent && parent->op != IPPFIND_OP_AND)
{
- temp->parent = parent;
- current->next = temp;
+ /*
+ * Need to re-group "current" in a new AND node...
+ */
+
+ ippfind_expr_t *tempand; /* Temporary AND node */
+
+ if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ /*
+ * Replace "current" with new AND node at the end of this list...
+ */
+
+ current->prev->next = tempand;
+ tempand->prev = current->prev;
+ tempand->parent = parent;
+
+ /*
+ * Add "current to the new AND node...
+ */
+
+ tempand->child = current;
+ current->parent = tempand;
+ current->prev = NULL;
+ parent = tempand;
}
+
+ /*
+ * Add the new node at current level...
+ */
+
+ temp->parent = parent;
+ temp->prev = current;
+
+ if (current)
+ current->next = temp;
else if (parent)
parent->child = temp;
else
expressions = temp;
- temp->prev = current;
- current = temp;
- invert = 0;
- temp = NULL;
+ current = temp;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
+ temp = NULL;
}
}
}
}
else if (!strcmp(argv[i], "("))
{
+ if (num_parens >= 100)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Too many parenthesis."));
+ show_usage();
+ }
+
if ((temp = new_expr(IPPFIND_OP_AND, invert, NULL, NULL, NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
+ parens[num_parens++] = temp;
+
if (current)
{
temp->parent = current->parent;
current->next = temp;
+ temp->prev = current;
}
else
expressions = temp;
- temp->prev = current;
- parent = temp;
- current = NULL;
- invert = 0;
- logic = IPPFIND_OP_AND;
+ parent = temp;
+ current = NULL;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
}
else if (!strcmp(argv[i], ")"))
{
- if (!parent)
+ if (num_parens <= 0)
{
_cupsLangPuts(stderr, _("ippfind: Missing open parenthesis."));
show_usage();
}
- current = parent;
+ current = parens[--num_parens];
parent = current->parent;
-
- if (!parent)
- logic = IPPFIND_OP_AND;
- else
- logic = parent->op;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
}
else if (!strcmp(argv[i], "!"))
{
}
}
- if (parent)
+ if (num_parens > 0)
{
_cupsLangPuts(stderr, _("ippfind: Missing close parenthesis."));
show_usage();
}
- if (cupsArrayCount(searches) == 0)
- {
- /*
- * Add an implicit browse for IPP printers ("_ipp._tcp")...
- */
-
- cupsArrayAdd(searches, "_ipp._tcp");
- }
-
if (!have_output)
{
/*
if (current)
{
- temp->parent = parent;
+ while (current->parent)
+ current = current->parent;
+
current->next = temp;
+ temp->prev = current;
}
else
expressions = temp;
+ }
+
+ if (cupsArrayCount(searches) == 0)
+ {
+ /*
+ * Add an implicit browse for IPP printers ("_ipp._tcp")...
+ */
+
+ cupsArrayAdd(searches, "_ipp._tcp");
+ }
+
+ if (getenv("IPPFIND_DEBUG"))
+ {
+ int indent = 4; /* Indentation */
+
+ puts("Expression tree:");
+ current = expressions;
+ while (current)
+ {
+ /*
+ * Print the current node...
+ */
+
+ printf("%*s%s%s\n", indent, "", current->invert ? "!" : "",
+ ops[current->op]);
+
+ /*
+ * Advance to the next node...
+ */
+
+ if (current->child)
+ {
+ current = current->child;
+ indent += 4;
+ }
+ else if (current->next)
+ current = current->next;
+ else if (current->parent)
+ {
+ while (current->parent)
+ {
+ indent -= 4;
+ current = current->parent;
+ if (current->next)
+ break;
+ }
+
+ current = current->next;
+ }
+ else
+ current = NULL;
+ }
- temp->prev = current;
+ puts("\nSearch items:");
+ for (search = (const char *)cupsArrayFirst(searches);
+ search;
+ search = (const char *)cupsArrayNext(searches))
+ printf(" %s\n", search);
}
/*
#elif defined(HAVE_AVAHI)
if ((avahi_poll = avahi_simple_poll_new()) == NULL)
{
- _cupsLangPrintError(stderr, _("ippfind: Unable to use Bonjour: %s"),
- strerror(errno));
+ _cupsLangPrintf(stderr, _("ippfind: Unable to use Bonjour: %s"),
+ strerror(errno));
return (IPPFIND_EXIT_BONJOUR);
}
avahi_client = avahi_client_new(avahi_simple_poll_get(avahi_poll),
0, client_callback, avahi_poll, &err);
- if (!client)
+ if (!avahi_client)
{
- _cupsLangPrintError(stderr, _("ippfind: Unable to use Bonjour: %s"),
- dnssd_error_string(err));
+ _cupsLangPrintf(stderr, _("ippfind: Unable to use Bonjour: %s"),
+ dnssd_error_string(err));
return (IPPFIND_EXIT_BONJOUR);
}
#endif /* HAVE_DNSSD */
*domain; /* Domain, if any */
strlcpy(buf, search, sizeof(buf));
- if (buf[0] == '_')
- {
- regtype = buf;
- }
- else if ((regtype = strstr(buf, "._")) != NULL)
+ if ((regtype = strstr(buf, "._")) != NULL)
{
- name = buf;
- *regtype++ = '\0';
+ if (strcmp(regtype, "._tcp"))
+ {
+ /*
+ * "something._protocol._tcp" -> search for something with the given
+ * protocol...
+ */
+
+ name = buf;
+ *regtype++ = '\0';
+ }
+ else
+ {
+ /*
+ * "_protocol._tcp" -> search for everything with the given protocol...
+ */
+
+ /* name = NULL; */
+ regtype = buf;
+ }
}
else
{
+ /*
+ * "something" -> search for something with IPP protocol...
+ */
+
name = buf;
regtype = "_ipp._tcp";
}
for (domain = regtype; *domain; domain ++)
+ {
if (*domain == '.' && domain[1] != '_')
{
- *domain++ = '\0';
- break;
+ *domain++ = '\0';
+ break;
}
+ }
if (!*domain)
domain = NULL;
if (service->ref)
err = 0;
else
- err = avahi_client_get_errno(avahi_client);
+ err = avahi_client_errno(avahi_client);
#endif /* HAVE_DNSSD */
}
else
browse_callback, services))
err = 0;
else
- err = avahi_client_get_errno(avahi_client);
+ err = avahi_client_errno(avahi_client);
#endif /* HAVE_DNSSD */
}
_cupsLangPrintf(stderr, _("ippfind: Unable to browse or resolve: %s"),
dnssd_error_string(err));
- if (name)
- printf("name=\"%s\"\n", name);
-
- printf("regtype=\"%s\"\n", regtype);
-
- if (domain)
- printf("domain=\"%s\"\n", domain);
-
return (IPPFIND_EXIT_BONJOUR);
}
}
if (service->ref)
err = 0;
else
- err = avahi_client_get_errno(avahi_client);
+ err = avahi_client_errno(avahi_client);
#endif /* HAVE_DNSSD */
if (err)
#ifdef HAVE_DNSSD
DNSServiceRefDeallocate(service->ref);
#else
- avahi_record_browser_free(service->ref);
+ avahi_service_resolver_free(service->ref);
#endif /* HAVE_DNSSD */
service->ref = NULL;
}
- if (!eval_expr(service, expressions))
- status = IPPFIND_EXIT_FALSE;
+ if (eval_expr(service, expressions))
+ status = IPPFIND_EXIT_TRUE;
service->is_processed = 1;
}
* 'browse_callback()' - Browse devices.
*/
-static void
+static void DNSSD_API
browse_callback(
DNSServiceRef sdRef, /* I - Service reference */
DNSServiceFlags flags, /* I - Option flags */
* Only process "add" data...
*/
+ (void)sdRef;
+ (void)interfaceIndex;
+
if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
return;
* 'browse_local_callback()' - Browse local devices.
*/
-static void
+static void DNSSD_API
browse_local_callback(
DNSServiceRef sdRef, /* I - Service reference */
DNSServiceFlags flags, /* I - Option flags */
* Only process "add" data...
*/
+ (void)sdRef;
+ (void)interfaceIndex;
+
if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
return;
fprintf(stderr, "DEBUG: browse_callback: %s\n",
avahi_strerror(avahi_client_errno(client)));
bonjour_error = 1;
- avahi_simple_poll_quit(simple_poll);
+ avahi_simple_poll_quit(avahi_poll);
break;
case AVAHI_BROWSER_NEW:
case kDNSServiceErr_PollingMode :
return ("Service polling mode error.");
+#ifndef WIN32
case kDNSServiceErr_Timeout :
return ("Service timeout.");
+#endif /* !WIN32 */
}
# elif defined(HAVE_AVAHI)
case IPPFIND_OP_NAME_REGEX :
result = !regexec(&(expression->re), service->name, 0, NULL, 0);
break;
+ case IPPFIND_OP_NAME_LITERAL :
+ result = !_cups_strcasecmp(expression->name, service->name);
+ break;
case IPPFIND_OP_HOST_REGEX :
result = !regexec(&(expression->re), service->host, 0, NULL, 0);
break;
result = !regexec(&(expression->re), service->resource, 0, NULL, 0);
break;
case IPPFIND_OP_TXT_EXISTS :
- result = cupsGetOption(expression->key, service->num_txt,
+ result = cupsGetOption(expression->name, service->num_txt,
service->txt) != NULL;
break;
case IPPFIND_OP_TXT_REGEX :
- val = cupsGetOption(expression->key, service->num_txt,
+ val = cupsGetOption(expression->name, service->num_txt,
service->txt);
if (val)
result = !regexec(&(expression->re), val, 0, NULL, 0);
else
result = 0;
+
+ if (getenv("IPPFIND_DEBUG"))
+ printf("TXT_REGEX of \"%s\": %d\n", val, result);
break;
case IPPFIND_OP_URI_REGEX :
result = !regexec(&(expression->re), service->uri, 0, NULL, 0);
break;
case IPPFIND_OP_EXEC :
result = exec_program(service, expression->num_args,
- expression->args);
+ expression->args);
break;
case IPPFIND_OP_LIST :
result = list_service(service);
int num_args, /* I - Number of command-line args */
char **args) /* I - Command-line arguments */
{
- (void)service;
- (void)num_args;
- (void)args;
+ char **myargv, /* Command-line arguments */
+ **myenvp, /* Environment variables */
+ *ptr, /* Pointer into variable */
+ domain[1024], /* IPPFIND_SERVICE_DOMAIN */
+ hostname[1024], /* IPPFIND_SERVICE_HOSTNAME */
+ name[256], /* IPPFIND_SERVICE_NAME */
+ port[32], /* IPPFIND_SERVICE_PORT */
+ regtype[256], /* IPPFIND_SERVICE_REGTYPE */
+ scheme[128], /* IPPFIND_SERVICE_SCHEME */
+ uri[1024], /* IPPFIND_SERVICE_URI */
+ txt[100][256]; /* IPPFIND_TXT_foo */
+ int i, /* Looping var */
+ myenvc, /* Number of environment variables */
+ status; /* Exit status of program */
+#ifndef WIN32
+ char program[1024]; /* Program to execute */
+ int pid; /* Process ID */
+#endif /* !WIN32 */
- return (1);
+
+ /*
+ * Environment variables...
+ */
+
+ snprintf(domain, sizeof(domain), "IPPFIND_SERVICE_DOMAIN=%s",
+ service->domain);
+ snprintf(hostname, sizeof(hostname), "IPPFIND_SERVICE_HOSTNAME=%s",
+ service->host);
+ snprintf(name, sizeof(name), "IPPFIND_SERVICE_NAME=%s", service->name);
+ snprintf(port, sizeof(port), "IPPFIND_SERVICE_PORT=%d", service->port);
+ snprintf(regtype, sizeof(regtype), "IPPFIND_SERVICE_REGTYPE=%s",
+ service->regtype);
+ snprintf(scheme, sizeof(scheme), "IPPFIND_SERVICE_SCHEME=%s",
+ !strncmp(service->regtype, "_http._tcp", 10) ? "http" :
+ !strncmp(service->regtype, "_https._tcp", 11) ? "https" :
+ !strncmp(service->regtype, "_ipp._tcp", 9) ? "ipp" :
+ !strncmp(service->regtype, "_ipps._tcp", 10) ? "ipps" : "lpd");
+ snprintf(uri, sizeof(uri), "IPPFIND_SERVICE_URI=%s", service->uri);
+ for (i = 0; i < service->num_txt && i < 100; i ++)
+ {
+ snprintf(txt[i], sizeof(txt[i]), "IPPFIND_TXT_%s=%s", service->txt[i].name,
+ service->txt[i].value);
+ for (ptr = txt[i] + 12; *ptr && *ptr != '='; ptr ++)
+ *ptr = (char)_cups_toupper(*ptr);
+ }
+
+ for (i = 0, myenvc = 7 + service->num_txt; environ[i]; i ++)
+ if (strncmp(environ[i], "IPPFIND_", 8))
+ myenvc ++;
+
+ if ((myenvp = calloc(sizeof(char *), (size_t)(myenvc + 1))) == NULL)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Out of memory."));
+ exit(IPPFIND_EXIT_MEMORY);
+ }
+
+ for (i = 0, myenvc = 0; environ[i]; i ++)
+ if (strncmp(environ[i], "IPPFIND_", 8))
+ myenvp[myenvc++] = environ[i];
+
+ myenvp[myenvc++] = domain;
+ myenvp[myenvc++] = hostname;
+ myenvp[myenvc++] = name;
+ myenvp[myenvc++] = port;
+ myenvp[myenvc++] = regtype;
+ myenvp[myenvc++] = scheme;
+ myenvp[myenvc++] = uri;
+
+ for (i = 0; i < service->num_txt && i < 100; i ++)
+ myenvp[myenvc++] = txt[i];
+
+ /*
+ * Allocate and copy command-line arguments...
+ */
+
+ if ((myargv = calloc(sizeof(char *), (size_t)(num_args + 1))) == NULL)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Out of memory."));
+ exit(IPPFIND_EXIT_MEMORY);
+ }
+
+ for (i = 0; i < num_args; i ++)
+ {
+ if (strchr(args[i], '{'))
+ {
+ char temp[2048], /* Temporary string */
+ *tptr, /* Pointer into temporary string */
+ keyword[256], /* {keyword} */
+ *kptr; /* Pointer into keyword */
+
+ for (ptr = args[i], tptr = temp; *ptr; ptr ++)
+ {
+ if (*ptr == '{')
+ {
+ /*
+ * Do a {var} substitution...
+ */
+
+ for (kptr = keyword, ptr ++; *ptr && *ptr != '}'; ptr ++)
+ if (kptr < (keyword + sizeof(keyword) - 1))
+ *kptr++ = *ptr;
+
+ if (*ptr != '}')
+ {
+ _cupsLangPuts(stderr,
+ _("ippfind: Missing close brace in substitution."));
+ exit(IPPFIND_EXIT_SYNTAX);
+ }
+
+ *kptr = '\0';
+ if (!keyword[0] || !strcmp(keyword, "service_uri"))
+ strlcpy(tptr, service->uri, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_domain"))
+ strlcpy(tptr, service->domain, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_hostname"))
+ strlcpy(tptr, service->host, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_name"))
+ strlcpy(tptr, service->name, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_path"))
+ strlcpy(tptr, service->resource, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_port"))
+ strlcpy(tptr, port + 21, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strcmp(keyword, "service_scheme"))
+ strlcpy(tptr, scheme + 22, sizeof(temp) - (size_t)(tptr - temp));
+ else if (!strncmp(keyword, "txt_", 4))
+ {
+ const char *val = cupsGetOption(keyword + 4, service->num_txt, service->txt);
+ if (val)
+ strlcpy(tptr, val, sizeof(temp) - (size_t)(tptr - temp));
+ else
+ *tptr = '\0';
+ }
+ else
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Unknown variable \"{%s}\"."),
+ keyword);
+ exit(IPPFIND_EXIT_SYNTAX);
+ }
+
+ tptr += strlen(tptr);
+ }
+ else if (tptr < (temp + sizeof(temp) - 1))
+ *tptr++ = *ptr;
+ }
+
+ *tptr = '\0';
+ myargv[i] = strdup(temp);
+ }
+ else
+ myargv[i] = strdup(args[i]);
+ }
+
+#ifdef WIN32
+ if (getenv("IPPFIND_DEBUG"))
+ {
+ printf("\nProgram:\n %s\n", args[0]);
+ puts("\nArguments:");
+ for (i = 0; i < num_args; i ++)
+ printf(" %s\n", myargv[i]);
+ puts("\nEnvironment:");
+ for (i = 0; i < myenvc; i ++)
+ printf(" %s\n", myenvp[i]);
+ }
+
+ status = _spawnvpe(_P_WAIT, args[0], myargv, myenvp);
+
+#else
+ /*
+ * Execute the program...
+ */
+
+ if (strchr(args[0], '/') && !access(args[0], X_OK))
+ strlcpy(program, args[0], sizeof(program));
+ else if (!cupsFileFind(args[0], getenv("PATH"), 1, program, sizeof(program)))
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Unable to execute \"%s\": %s"),
+ args[0], strerror(ENOENT));
+ exit(IPPFIND_EXIT_SYNTAX);
+ }
+
+ if (getenv("IPPFIND_DEBUG"))
+ {
+ printf("\nProgram:\n %s\n", program);
+ puts("\nArguments:");
+ for (i = 0; i < num_args; i ++)
+ printf(" %s\n", myargv[i]);
+ puts("\nEnvironment:");
+ for (i = 0; i < myenvc; i ++)
+ printf(" %s\n", myenvp[i]);
+ }
+
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child comes here...
+ */
+
+ execve(program, myargv, myenvp);
+ exit(1);
+ }
+ else if (pid < 0)
+ {
+ _cupsLangPrintf(stderr, _("ippfind: Unable to execute \"%s\": %s"),
+ args[0], strerror(errno));
+ exit(IPPFIND_EXIT_SYNTAX);
+ }
+ else
+ {
+ /*
+ * Wait for it to complete...
+ */
+
+ while (wait(&status) != pid)
+ ;
+ }
+#endif /* WIN32 */
+
+ /*
+ * Free memory...
+ */
+
+ for (i = 0; i < num_args; i ++)
+ free(myargv[i]);
+
+ free(myargv);
+ free(myenvp);
+
+ /*
+ * Return whether the program succeeded or crashed...
+ */
+
+ if (getenv("IPPFIND_DEBUG"))
+ {
+#ifdef WIN32
+ printf("Exit Status: %d\n", status);
+#else
+ if (WIFEXITED(status))
+ printf("Exit Status: %d\n", WEXITSTATUS(status));
+ else
+ printf("Terminating Signal: %d\n", WTERMSIG(status));
+#endif /* WIN32 */
+ }
+
+ return (status == 0);
}
static int /* O - 1 if successful, 0 otherwise */
list_service(ippfind_srv_t *service) /* I - Service */
{
- (void)service;
+ http_addrlist_t *addrlist; /* Address(es) of service */
+ char port[10]; /* Port number of service */
+
+
+ snprintf(port, sizeof(port), "%d", service->port);
+
+ if ((addrlist = httpAddrGetList(service->host, address_family, port)) == NULL)
+ {
+ _cupsLangPrintf(stdout, "%s unreachable", service->uri);
+ return (0);
+ }
+
+ if (!strncmp(service->regtype, "_ipp._tcp", 9) ||
+ !strncmp(service->regtype, "_ipps._tcp", 10))
+ {
+ /*
+ * IPP/IPPS printer
+ */
+
+ http_t *http; /* HTTP connection */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ int i, /* Looping var */
+ count, /* Number of values */
+ version, /* IPP version */
+ paccepting; /* printer-is-accepting-jobs value */
+ ipp_pstate_t pstate; /* printer-state value */
+ char preasons[1024], /* Comma-delimited printer-state-reasons */
+ *ptr, /* Pointer into reasons */
+ *end; /* End of reasons buffer */
+ static const char * const rattrs[] =/* Requested attributes */
+ {
+ "printer-is-accepting-jobs",
+ "printer-state",
+ "printer-state-reasons"
+ };
+
+ /*
+ * Connect to the printer...
+ */
+
+ http = httpConnect2(service->host, service->port, addrlist, address_family,
+ !strncmp(service->regtype, "_ipps._tcp", 10) ?
+ HTTP_ENCRYPTION_ALWAYS :
+ HTTP_ENCRYPTION_IF_REQUESTED,
+ 1, 30000, NULL);
+
+ httpAddrFreeList(addrlist);
+
+ if (!http)
+ {
+ _cupsLangPrintf(stdout, "%s unavailable", service->uri);
+ return (0);
+ }
+
+ /*
+ * Get the current printer state...
+ */
+
+ response = NULL;
+ version = ipp_version;
+
+ do
+ {
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippSetVersion(request, version / 10, version % 10);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ service->uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ (int)(sizeof(rattrs) / sizeof(rattrs[0])), NULL, rattrs);
+
+ response = cupsDoRequest(http, request, service->resource);
+
+ if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST && version > 11)
+ version = 11;
+ }
+ while (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE && version > 11);
+
+ /*
+ * Show results...
+ */
+
+ if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE)
+ {
+ _cupsLangPrintf(stdout, "%s: unavailable", service->uri);
+ return (0);
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-state",
+ IPP_TAG_ENUM)) != NULL)
+ pstate = (ipp_pstate_t)ippGetInteger(attr, 0);
+ else
+ pstate = IPP_PSTATE_STOPPED;
+
+ if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
+ IPP_TAG_BOOLEAN)) != NULL)
+ paccepting = ippGetBoolean(attr, 0);
+ else
+ paccepting = 0;
+
+ if ((attr = ippFindAttribute(response, "printer-state-reasons",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ strlcpy(preasons, ippGetString(attr, 0, NULL), sizeof(preasons));
+
+ for (i = 1, count = ippGetCount(attr), ptr = preasons + strlen(preasons),
+ end = preasons + sizeof(preasons) - 1;
+ i < count && ptr < end;
+ i ++, ptr += strlen(ptr))
+ {
+ *ptr++ = ',';
+ strlcpy(ptr, ippGetString(attr, i, NULL), (size_t)(end - ptr + 1));
+ }
+ }
+ else
+ strlcpy(preasons, "none", sizeof(preasons));
+
+ ippDelete(response);
+ httpClose(http);
+
+ _cupsLangPrintf(stdout, "%s %s %s %s", service->uri,
+ ippEnumString("printer-state", pstate),
+ paccepting ? "accepting-jobs" : "not-accepting-jobs",
+ preasons);
+ }
+ else if (!strncmp(service->regtype, "_http._tcp", 10) ||
+ !strncmp(service->regtype, "_https._tcp", 11))
+ {
+ /*
+ * HTTP/HTTPS web page
+ */
+
+ http_t *http; /* HTTP connection */
+ http_status_t status; /* HEAD status */
+
+
+ /*
+ * Connect to the web server...
+ */
+
+ http = httpConnect2(service->host, service->port, addrlist, address_family,
+ !strncmp(service->regtype, "_ipps._tcp", 10) ?
+ HTTP_ENCRYPTION_ALWAYS :
+ HTTP_ENCRYPTION_IF_REQUESTED,
+ 1, 30000, NULL);
+
+ httpAddrFreeList(addrlist);
+
+ if (!http)
+ {
+ _cupsLangPrintf(stdout, "%s unavailable", service->uri);
+ return (0);
+ }
+
+ if (httpGet(http, service->resource))
+ {
+ _cupsLangPrintf(stdout, "%s unavailable", service->uri);
+ return (0);
+ }
+
+ do
+ {
+ status = httpUpdate(http);
+ }
+ while (status == HTTP_STATUS_CONTINUE);
+
+ httpFlush(http);
+ httpClose(http);
+
+ if (status >= HTTP_STATUS_BAD_REQUEST)
+ {
+ _cupsLangPrintf(stdout, "%s unavailable", service->uri);
+ return (0);
+ }
+
+ _cupsLangPrintf(stdout, "%s available", service->uri);
+ }
+ else if (!strncmp(service->regtype, "_printer._tcp", 13))
+ {
+ /*
+ * LPD printer
+ */
+
+ int sock; /* Socket */
+
+
+ if (!httpAddrConnect(addrlist, &sock))
+ {
+ _cupsLangPrintf(stdout, "%s unavailable", service->uri);
+ httpAddrFreeList(addrlist);
+ return (0);
+ }
+
+ _cupsLangPrintf(stdout, "%s available", service->uri);
+ httpAddrFreeList(addrlist);
+
+ httpAddrClose(NULL, sock);
+ }
+ else
+ {
+ _cupsLangPrintf(stdout, "%s unsupported", service->uri);
+ httpAddrFreeList(addrlist);
+ return (0);
+ }
return (1);
}
temp->op = op;
temp->invert = invert;
- if (op == IPPFIND_OP_TXT_EXISTS || op == IPPFIND_OP_TXT_REGEX)
- temp->key = (char *)value;
+ if (op == IPPFIND_OP_TXT_EXISTS || op == IPPFIND_OP_TXT_REGEX || op == IPPFIND_OP_NAME_LITERAL)
+ temp->name = (char *)value;
else if (op == IPPFIND_OP_PORT_RANGE)
{
/*
if (!strcmp(args[num_args], ";"))
break;
- temp->args = malloc(num_args * sizeof(char *));
- memcpy(temp->args, args, num_args * sizeof(char *));
+ temp->num_args = num_args;
+ temp->args = malloc((size_t)num_args * sizeof(char *));
+ memcpy(temp->args, args, (size_t)num_args * sizeof(char *));
}
return (temp);
val = poll(pollfds, num_pollfds, 500);
- if (val < 0)
- fprintf(stderr, "DEBUG: poll_callback: %s\n", strerror(errno));
- else if (val > 0)
- got_data = 1;
+ if (val > 0)
+ avahi_got_data = 1;
return (val);
}
*/
#ifdef HAVE_DNSSD
-static void
+static void DNSSD_API
resolve_callback(
DNSServiceRef sdRef, /* I - Service reference */
DNSServiceFlags flags, /* I - Data flags */
* Only process "add" data...
*/
- if (errorCode != kDNSServiceErr_NoError)
+ (void)sdRef;
+ (void)flags;
+ (void)interfaceIndex;
+ (void)fullName;
+
+ if (errorCode != kDNSServiceErr_NoError)
{
_cupsLangPrintf(stderr, _("ippfind: Unable to browse or resolve: %s"),
dnssd_error_string(errorCode));
service->host = strdup(hostTarget);
service->port = ntohs(port);
+ value = service->host + strlen(service->host) - 1;
+ if (value >= service->host && *value == '.')
+ *value = '\0';
+
/*
* Loop through the TXT key/value pairs and add them to an array...
*/
AvahiServiceResolver *resolver, /* I - Resolver */
AvahiIfIndex interface, /* I - Interface */
AvahiProtocol protocol, /* I - Address protocol */
- AvahiBrowserEvent event, /* I - Event */
+ AvahiResolverEvent event, /* I - Event */
const char *serviceName,/* I - Service name */
const char *regtype, /* I - Registration type */
const char *replyDomain,/* I - Domain name */
const char *hostTarget, /* I - FQDN */
+ const AvahiAddress *address, /* I - Address */
uint16_t port, /* I - Port number */
AvahiStringList *txt, /* I - TXT records */
AvahiLookupResultFlags flags, /* I - Lookup flags */
void *context) /* I - Service */
{
- char uri[1024]; /* URI */
- key[256], /* TXT key */
+ char key[256], /* TXT key */
*value; /* TXT value */
ippfind_srv_t *service = (ippfind_srv_t *)context;
/* Service */
AvahiStringList *current; /* Current TXT key/value pair */
+ (void)address;
+
if (event != AVAHI_RESOLVER_FOUND)
{
bonjour_error = 1;
avahi_service_resolver_free(resolver);
- avahi_simple_poll_quit(uribuf->poll);
+ avahi_simple_poll_quit(avahi_poll);
return;
}
service->is_resolved = 1;
service->host = strdup(hostTarget);
- service->port = ntohs(port);
+ service->port = port;
+
+ value = service->host + strlen(service->host) - 1;
+ if (value >= service->host && *value == '.')
+ *value = '\0';
/*
* Loop through the TXT key/value pairs and add them to an array...
_cupsLangPuts(stderr, _("Expressions:"));
_cupsLangPuts(stderr, _(" -P number[-number] Match port to number or range."));
_cupsLangPuts(stderr, _(" -d regex Match domain to regular expression."));
- _cupsLangPuts(stderr, _(" -e utility [argument ...] ;\n"
- " Execute program if true."));
_cupsLangPuts(stderr, _(" -h regex Match hostname to regular expression."));
_cupsLangPuts(stderr, _(" -l List attributes."));
_cupsLangPuts(stderr, _(" -n regex Match service name to regular expression."));
_cupsLangPuts(stderr, _(" -s Print service name if true."));
_cupsLangPuts(stderr, _(" -t key True if the TXT record contains the key."));
_cupsLangPuts(stderr, _(" -u regex Match URI to regular expression."));
+ _cupsLangPuts(stderr, _(" -x utility [argument ...] ;\n"
+ " Execute program if true."));
_cupsLangPuts(stderr, _(" --domain regex Match domain to regular expression."));
_cupsLangPuts(stderr, _(" --exec utility [argument ...] ;\n"
" Execute program if true."));
exit(IPPFIND_EXIT_TRUE);
}
-
-
-/*
- * End of "$Id$".
- */