[master] 154aea3 Fix parsing of -f arguments in varnishstat (and vsc)

Martin Blix Grydeland martin at varnish-cache.org
Tue Nov 19 17:37:57 CET 2013


commit 154aea3248aa7465878f8261ef3b528c111d882e
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Tue Nov 19 15:23:48 2013 +0100

    Fix parsing of -f arguments in varnishstat (and vsc)
    
    Removed the comma-separated delimiting of this option parsing, as that
    conflicted with comma characters often used in backend names. Use
    multiple arguments to have several filters.
    
    Parser honors backslash escapes. This makes it possible to list names
    containing '.' (also common with backend names).
    
    Fixes: #957

diff --git a/bin/varnishstat/varnishstat.c b/bin/varnishstat/varnishstat.c
index a11a44a..543b0e3 100644
--- a/bin/varnishstat/varnishstat.c
+++ b/bin/varnishstat/varnishstat.c
@@ -242,8 +242,7 @@ usage(void)
 	    VSC_n_USAGE " "
 	    "[-w delay]\n");
 	fprintf(stderr, FMT, "-1", "Print the statistics to stdout.");
-	fprintf(stderr, FMT, "-f field_list",
-	    "Comma separated list of fields to display. ");
+	fprintf(stderr, FMT, "-f field_list", "Field inclusion glob");
 	fprintf(stderr, FMT, "",
 	    "If it starts with '^' it is used as an exclusion list");
 	fprintf(stderr, FMT, "-l",
diff --git a/doc/sphinx/reference/varnishstat.rst b/doc/sphinx/reference/varnishstat.rst
index 703df32..c27af28 100644
--- a/doc/sphinx/reference/varnishstat.rst
+++ b/doc/sphinx/reference/varnishstat.rst
@@ -30,8 +30,13 @@ The following options are available:
 
 -1          Instead of presenting of a continuously updated display, print the statistics to stdout.
 
--f          A comma separated list of the fields to display.  If it starts with '^' it is used as an exclusion
-	    list.
+-f          Field inclusion glob. A field glob consists of three
+            parts, type, ident and name, where ident is optional. Each
+            part can contain a '*' character at the end to match a
+            prefix. Use backslash to escape characters. If the
+            argument starts with '^' it is used as an exclusion
+            glob. Multiple -f arguments may be given, and they will be
+            applied in order.
 
 -l          Lists the available fields to use with the -f option.
 
diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c
index 2df4d9e..1ea0348 100644
--- a/lib/libvarnishapi/vsc.c
+++ b/lib/libvarnishapi/vsc.c
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include <stdio.h>
 #include <errno.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -44,7 +45,6 @@
 #include "vapi/vsc.h"
 #include "vapi/vsm.h"
 #include "vapi/vsm_int.h"
-#include "vav.h"
 #include "vqueue.h"
 #include "vsm_api.h"
 
@@ -179,85 +179,106 @@ vsc_f_arg(struct VSM_data *vd, const char *opt)
 {
 	struct vsc *vsc = vsc_setup(vd);
 	struct vsc_sf *sf;
-	char **av, *q, *p;
+	const char *error = NULL;
+	const char *p, *q;
+	char *r;
 	int i;
+	int flags = 0;
+	char *parts[3];
+
+	AN(vd);
+	AN(opt);
 
-	av = VAV_Parse(opt, NULL, ARGV_COMMA);
-	AN(av);
-	if (av[0] != NULL) {
-		i = vsm_diag(vd, "Parse error: %s", av[0]);
-		VAV_Free(av);
-		return (i);
+	if (opt[0] == '^') {
+		flags |= VSC_SF_EXCL;
+		opt++;
 	}
-	for (i = 1; av[i] != NULL; i++) {
-		ALLOC_OBJ(sf, VSC_SF_MAGIC);
-		AN(sf);
-		VTAILQ_INSERT_TAIL(&vsc->sf_list, sf, list);
-
-		p = av[i];
-		if (*p == '^') {
-			sf->flags |= VSC_SF_EXCL;
-			p++;
-		}
 
-		q = strchr(p, '.');
-		if (q != NULL) {
-			*q++ = '\0';
-			if (*p != '\0')
-				REPLACE(sf->type, p);
-			p = q;
-			if (*p != '\0') {
-				q = strchr(p, '.');
-				if (q != NULL) {
-					*q++ = '\0';
-					if (*p != '\0')
-						REPLACE(sf->ident, p);
-					p = q;
-				}
+	/* Split on '.' */
+	memset(parts, 0, sizeof parts);
+	for (i = 0, p = opt; *p != '\0'; i++) {
+		for (q = p; *q != '\0' && *q != '.'; q++)
+			if (*q == '\\')
+				q++;
+		if (i < 3) {
+			parts[i] = strndup(p, q - p);
+			AN(parts[i]);
+			p = r = parts[i];
+
+			/* Unescape */
+			while (1) {
+				if (*p == '\\')
+					p++;
+				if (*p == '\0')
+					break;
+				*r++ = *p++;
 			}
+			*r = '\0';
 		}
-		if (*p != '\0') {
-			REPLACE(sf->name, p);
-		}
+		p = q;
+		if (*p == '.')
+			p++;
+	}
+	if (i < 1 || i > 3) {
+		(void)vsm_diag(vd, "-f: Wrong number of elements");
+		for (i = 0; i < 3; i++)
+			free(parts[i]);
+		return (-1);
+	}
 
-		/* Check for wildcards */
-		if (sf->type != NULL) {
-			q = strchr(sf->type, '*');
-			if (q != NULL && q[1] == '\0') {
-				*q = '\0';
-				sf->flags |= VSC_SF_TY_WC;
-			} else if (q != NULL) {
-				i = -1;
-				break;
-			}
-		}
-		if (sf->ident != NULL) {
-			q = strchr(sf->ident, '*');
-			if (q != NULL && q[1] == '\0') {
-				*q = '\0';
-				sf->flags |= VSC_SF_ID_WC;
-			} else if (q != NULL) {
-				i = -1;
-				break;
-			}
-		}
-		if (sf->name != NULL) {
-			q = strchr(sf->name, '*');
-			if (q != NULL && q[1] == '\0') {
-				*q = '\0';
-				sf->flags |= VSC_SF_NM_WC;
-			} else if (q != NULL) {
-				i = -1;
-				break;
-			}
-		}
+	/* Set fields */
+	ALLOC_OBJ(sf, VSC_SF_MAGIC);
+	AN(sf);
+	sf->flags = flags;
+	AN(parts[0]);
+	sf->type = parts[0];
+	if (i == 2) {
+		AN(parts[1]);
+		sf->name = parts[1];
+	} else if (i == 3) {
+		AN(parts[1]);
+		sf->ident = parts[1];
+		AN(parts[2]);
+		sf->name = parts[2];
 	}
-	if (i < 0)
-		i = vsm_diag(vd, "Wildcard error: %s", opt);
-	else
-		i = 1;
-	VAV_Free(av);
-	return (i);
+
+	/* Check for wildcards */
+	if (sf->type != NULL) {
+		r = strchr(sf->type, '*');
+		if (r != NULL && r[1] == '\0') {
+			*r = '\0';
+			sf->flags |= VSC_SF_TY_WC;
+		} else if (r != NULL)
+			error = "-f: Wildcard not last";
+	}
+	if (sf->ident != NULL) {
+		r = strchr(sf->ident, '*');
+		if (r != NULL && r[1] == '\0') {
+			*r = '\0';
+			sf->flags |= VSC_SF_ID_WC;
+		} else if (r != NULL)
+			error = "-f: Wildcard not last";
+	}
+	if (sf->name != NULL) {
+		r = strchr(sf->name, '*');
+		if (r != NULL && r[1] == '\0') {
+			*r = '\0';
+			sf->flags |= VSC_SF_NM_WC;
+		} else if (r != NULL)
+			error = "-f: Wildcard not last";
+	}
+
+	if (error != NULL) {
+		(void)vsm_diag(vd, "%s", error);
+		free(sf->type);
+		free(sf->ident);
+		free(sf->name);
+		FREE_OBJ(sf);
+		return (-1);
+	}
+
+	VTAILQ_INSERT_TAIL(&vsc->sf_list, sf, list);
+	return (1);
 }
 
 /*--------------------------------------------------------------------*/



More information about the varnish-commit mailing list