summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-06-06 22:08:14 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-06-06 22:08:14 +0000
commit2d0a0f48e7c5fb8e97b49972250e0b04b5d735fb (patch)
treeeb6f7dee598d0959fd35a793c95cd1ad0d7fff0c
parent70752071b3b064ddda12662cbfa66fc46eb9eace (diff)
<rdar://problem/13876199> cups.org: Need ippfind command-line utility
Implement --exec. The ippfind command is now feature complete for CUPS 1.7. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11021 a1ca3aef-8c08-0410-bb20-df032aa958be
-rw-r--r--cups/string-private.h16
-rw-r--r--test/ippfind.c230
2 files changed, 238 insertions, 8 deletions
diff --git a/cups/string-private.h b/cups/string-private.h
index bef1aea80..8255bfdfb 100644
--- a/cups/string-private.h
+++ b/cups/string-private.h
@@ -3,7 +3,7 @@
*
* Private string definitions for CUPS.
*
- * Copyright 2007-2011 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -102,6 +102,12 @@ _cups_isalpha(int ch) /* I - Character to test */
}
_CUPS_INLINE int /* O - 1 on match, 0 otherwise */
+_cups_islower(int ch) /* I - Character to test */
+{
+ return (ch >= 'a' && ch <= 'z');
+}
+
+_CUPS_INLINE int /* O - 1 on match, 0 otherwise */
_cups_isspace(int ch) /* I - Character to test */
{
return (ch == ' ' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' ||
@@ -119,12 +125,20 @@ _cups_tolower(int ch) /* I - Character to convert */
{
return (_cups_isupper(ch) ? ch - 'A' + 'a' : ch);
}
+
+_CUPS_INLINE int /* O - Converted character */
+_cups_toupper(int ch) /* I - Character to convert */
+{
+ return (_cups_islower(ch) ? ch - 'a' + 'A' : ch);
+}
# else
extern int _cups_isalnum(int ch);
extern int _cups_isalpha(int ch);
+extern int _cups_islower(int ch);
extern int _cups_isspace(int ch);
extern int _cups_isupper(int ch);
extern int _cups_tolower(int ch);
+extern int _cups_toupper(int ch);
# endif /* _CUPS_INLINE */
diff --git a/test/ippfind.c b/test/ippfind.c
index 5c5f11a4c..d8dfe5f42 100644
--- a/test/ippfind.c
+++ b/test/ippfind.c
@@ -58,6 +58,8 @@
# define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX
#endif /* HAVE_DNSSD */
+extern char **environ; /* Process environment variables */
+
/*
* Structures...
@@ -1815,7 +1817,7 @@ eval_expr(ippfind_srv_t *service, /* I - Service */
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);
@@ -1856,11 +1858,224 @@ exec_program(ippfind_srv_t *service, /* I - 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 = _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 *), 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 *), 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) - (tptr - temp));
+ else if (!strcmp(keyword, "service_domain"))
+ strlcpy(tptr, service->domain, sizeof(temp) - (tptr - temp));
+ else if (!strcmp(keyword, "service_hostname"))
+ strlcpy(tptr, service->host, sizeof(temp) - (tptr - temp));
+ else if (!strcmp(keyword, "service_name"))
+ strlcpy(tptr, service->name, sizeof(temp) - (tptr - temp));
+ else if (!strcmp(keyword, "service_path"))
+ strlcpy(tptr, service->resource, sizeof(temp) - (tptr - temp));
+ else if (!strcmp(keyword, "service_port"))
+ strlcpy(tptr, port + 20, sizeof(temp) - (tptr - temp));
+ else if (!strcmp(keyword, "service_scheme"))
+ strlcpy(tptr, scheme + 22, sizeof(temp) - (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) - (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
+ 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]);
+
+ /*
+ * Return whether the program succeeded or crashed...
+ */
+
+ return (status == 0);
}
@@ -1957,7 +2172,7 @@ static int /* O - 1 if successful, 0 otherwise */
list_service(ippfind_srv_t *service) /* I - Service */
{
http_addrlist_t *addrlist; /* Address(es) of service */
- char port[32]; /* Port number of service */
+ char port[10]; /* Port number of service */
snprintf(port, sizeof(port), "%d", service->port);
@@ -2240,7 +2455,8 @@ new_expr(ippfind_op_t op, /* I - Operation */
if (!strcmp(args[num_args], ";"))
break;
- temp->args = malloc(num_args * sizeof(char *));
+ temp->num_args = num_args;
+ temp->args = malloc(num_args * sizeof(char *));
memcpy(temp->args, args, num_args * sizeof(char *));
}