/*
- * "$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.
*
- * Copyright 2008-2014 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/".
+ * Copyright © 2008-2018 by Apple Inc.
*
- * This file is subject to the Apple OS-Developed Software exception.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
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 */
*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 */
"IS_REMOTE",
"DOMAIN_REGEX",
"NAME_REGEX",
+ "NAME_LITERAL",
"HOST_REGEX",
"PORT_RANGE",
"PATH_REGEX",
* 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] == '-')
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_NAME_LITERAL, invert, argv[i], NULL, NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+ }
else if (!strcmp(argv[i], "--name"))
{
i ++;
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)
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)
*domain; /* Domain, if any */
strlcpy(buf, search, sizeof(buf));
- if (buf[0] == '_')
+ if ((regtype = strstr(buf, "._")) != NULL)
{
- regtype = buf;
- }
- else 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;
_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);
}
}
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);
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 + 20, sizeof(temp) - (size_t)(tptr - temp));
+ 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))
{
- if ((ptr = (char *)cupsGetOption(keyword + 4, service->num_txt,
- service->txt)) != NULL)
- strlcpy(tptr, strdup(ptr), sizeof(temp) - (size_t)(tptr - temp));
+ 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';
}
}
#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
* 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);
}
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)
{
/*
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...
*/
service->host = strdup(hostTarget);
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...
*/
exit(IPPFIND_EXIT_TRUE);
}
-
-
-/*
- * End of "$Id$".
- */