r5588 - in trunk/varnish-cache: bin/varnishtest include lib/libvarnish

phk at varnish-cache.org phk at varnish-cache.org
Thu Nov 25 15:46:34 CET 2010


Author: phk
Date: 2010-11-25 15:46:34 +0100 (Thu, 25 Nov 2010)
New Revision: 5588

Modified:
   trunk/varnish-cache/bin/varnishtest/vtc_varnish.c
   trunk/varnish-cache/include/cli_common.h
   trunk/varnish-cache/lib/libvarnish/cli_serve.c
Log:
Add a new feature to the CLI syntax:  Bourne-shell like "here" documents.

The last argument to any CLI command can use this feature.

Typical example:

	vcl.inline vcl_new << 42
	backend foo {...}
	sub vcl_recv {...}
	42

The advantage is that no escaping is needed, as long as the magic
marker, in this case "42" does not match any line anywhere in the 
lines that make up the argument.

Arguments encoded this way are not subject to the "cli_buffer"
parameters size limitation.



Modified: trunk/varnish-cache/bin/varnishtest/vtc_varnish.c
===================================================================
--- trunk/varnish-cache/bin/varnishtest/vtc_varnish.c	2010-11-22 11:12:45 UTC (rev 5587)
+++ trunk/varnish-cache/bin/varnishtest/vtc_varnish.c	2010-11-25 14:46:34 UTC (rev 5588)
@@ -33,7 +33,6 @@
 
 #include <stdio.h>
 
-#include <ctype.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -80,6 +79,8 @@
 	struct VSM_data		*vd;
 };
 
+#define NONSENSE	"%XJEIFLH|)Xspa8P"
+
 static VTAILQ_HEAD(, varnish)	varnishes =
     VTAILQ_HEAD_INITIALIZER(varnishes);
 
@@ -117,28 +118,6 @@
 	return ((enum cli_status_e)retval);
 }
 
-static void
-varnish_cli_encode(struct vsb *vsb, const char *str)
-{
-
-	for (; *str != '\0'; str++) {
-		switch (*str) {
-		case '\\':
-		case '"':
-			vsb_printf(vsb, "\\%c", *str); break;
-		case '\n':
-			vsb_printf(vsb, "\\n"); break;
-		case '\t':
-			vsb_printf(vsb, "\\t"); break;
-		default:
-			if (isgraph(*str) || *str == ' ')
-				vsb_putc(vsb, *str);
-			else
-				vsb_printf(vsb, "\\x%02x", *str);
-		}
-	}
-}
-
 /**********************************************************************
  * Allocate and initialize a varnish
  */
@@ -523,10 +502,8 @@
 	vsb = vsb_newauto();
 	AN(vsb);
 
-	v->vcl_nbr++;
-	vsb_printf(vsb, "vcl.inline vcl%d \"", v->vcl_nbr);
-	varnish_cli_encode(vsb, vcl);
-	vsb_printf(vsb, "\"", *vcl);
+	vsb_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n",
+	    ++v->vcl_nbr, NONSENSE, vcl, NONSENSE);
 	vsb_finish(vsb);
 	AZ(vsb_overflowed(vsb));
 
@@ -575,14 +552,8 @@
 	vsb_finish(vsb2);
 	AZ(vsb_overflowed(vsb2));
 
-	v->vcl_nbr++;
-	vsb_printf(vsb, "vcl.inline vcl%d \"", v->vcl_nbr);
-
-	varnish_cli_encode(vsb, vsb_data(vsb2));
-
-	varnish_cli_encode(vsb, vcl);
-
-	vsb_printf(vsb, "\"", *vcl);
+	vsb_printf(vsb, "vcl.inline vcl%d << %s\n%s\n%s\n%s\n",
+	    ++v->vcl_nbr, NONSENSE, vsb_data(vsb2), vcl, NONSENSE);
 	vsb_finish(vsb);
 	AZ(vsb_overflowed(vsb));
 

Modified: trunk/varnish-cache/include/cli_common.h
===================================================================
--- trunk/varnish-cache/include/cli_common.h	2010-11-22 11:12:45 UTC (rev 5587)
+++ trunk/varnish-cache/include/cli_common.h	2010-11-25 14:46:34 UTC (rev 5588)
@@ -37,7 +37,7 @@
 #define CLI_MAGIC		0x4038d570
 	struct vsb		*sb;
 	enum cli_status_e	result;
-	const char		*cmd;
+	char			*cmd;
 	unsigned		auth;
 	char			challenge[34];
 	char			*ident;

Modified: trunk/varnish-cache/lib/libvarnish/cli_serve.c
===================================================================
--- trunk/varnish-cache/lib/libvarnish/cli_serve.c	2010-11-22 11:12:45 UTC (rev 5587)
+++ trunk/varnish-cache/lib/libvarnish/cli_serve.c	2010-11-25 14:46:34 UTC (rev 5588)
@@ -68,6 +68,9 @@
 	struct cli			*cli, clis;
 	cls_cb_f			*closefunc;
 	void				*priv;
+	struct vsb			*last_arg;
+	int				last_idx;
+	char				**argv;
 };
 
 struct cls {
@@ -234,13 +237,12 @@
  */
 
 static int
-cls_vlu(void *priv, const char *p)
+cls_vlu2(void *priv, char * const *av)
 {
 	struct cls_fd *cfd;
 	struct cls *cs;
 	struct cls_func *cfn;
 	struct cli *cli;
-	char * * av;
 	unsigned na;
 
 	CAST_OBJ_NOTNULL(cfd, priv, CLS_FD_MAGIC);
@@ -249,23 +251,10 @@
 
 	cli = cfd->cli;
 	CHECK_OBJ_NOTNULL(cli, CLI_MAGIC);
-	AZ(cli->cmd);
+	AN(cli->cmd);
 
-	/*
-	 * Lines with only whitespace are simply ignored, in order to not
-	 * complicate CLI-client side scripts and TELNET users
-	 */
-	for (; isspace(*p); p++)
-		continue;
-	if (*p == '\0')
-		return (0);
-
-	cli->cmd = p;
 	cli->cls = cs;
 
-	av = ParseArgv(p, 0);
-	AN(av);
-
 	cli->result = CLIS_UNKNOWN;
 	vsb_clear(cli->sb);
 	cli_out(cli, "Unknown request.\nType 'help' for more info.\n");
@@ -306,9 +295,7 @@
 	if (cs->after != NULL)
 		cs->after(cli);
 
-	cli->cmd = NULL;
 	cli->cls = NULL;
-	FreeArgv(av);
 
 	if (cli_writeres(cfd->fdo, cli) || cli->result == CLIS_CLOSE)
 		return (1);
@@ -316,6 +303,82 @@
 	return (0);
 }
 
+static int
+cls_vlu(void *priv, const char *p)
+{
+	struct cls_fd *cfd;
+	struct cli *cli;
+	int i;
+	char **av;
+
+	CAST_OBJ_NOTNULL(cfd, priv, CLS_FD_MAGIC);
+
+	cli = cfd->cli;
+	CHECK_OBJ_NOTNULL(cli, CLI_MAGIC);
+
+	if (cfd->argv == NULL) {
+		/*
+		 * Lines with only whitespace are simply ignored, in order
+		 * to not complicate CLI-client side scripts and TELNET users
+		 */
+		for (; isspace(*p); p++)
+			continue;
+		if (*p == '\0')
+			return (0);
+		REPLACE(cli->cmd, p);
+
+		av = ParseArgv(p, 0);
+		AN(av);
+		if (av[0] != NULL) {
+			i = cls_vlu2(priv, av);
+			FreeArgv(av);	
+			free(cli->cmd);
+			cli->cmd = NULL;
+			return (i);
+		}
+		for (i = 1; av[i] != NULL; i++)
+			continue;
+		if (i < 3 || strcmp(av[i - 2], "<<")) {
+			i = cls_vlu2(priv, av);
+			FreeArgv(av);	
+			free(cli->cmd);
+			cli->cmd = NULL;
+			return (i);
+		}
+		cfd->argv = av;
+		cfd->last_idx = i - 2;
+		cfd->last_arg = vsb_newauto();
+		AN(cfd->last_arg);
+		return (0);
+	} else {
+		AN(cfd->argv[cfd->last_idx]);
+		assert(!strcmp(cfd->argv[cfd->last_idx], "<<"));
+		AN(cfd->argv[cfd->last_idx + 1]);
+		if (strcmp(p, cfd->argv[cfd->last_idx + 1])) {
+			vsb_cat(cfd->last_arg, p);
+			vsb_cat(cfd->last_arg, "\n");
+			return (0);
+		}
+		vsb_finish(cfd->last_arg);
+		AZ(vsb_overflowed(cfd->last_arg));
+		free(cfd->argv[cfd->last_idx]);
+		cfd->argv[cfd->last_idx] = NULL;
+		free(cfd->argv[cfd->last_idx + 1]);
+		cfd->argv[cfd->last_idx + 1] = NULL;
+		cfd->argv[cfd->last_idx] = vsb_data(cfd->last_arg);
+		i = cls_vlu2(priv, cfd->argv);
+		cfd->argv[cfd->last_idx] = NULL;
+		FreeArgv(cfd->argv);	
+		cfd->argv = NULL;
+		free(cli->cmd);
+		cli->cmd = NULL;
+		vsb_delete(cfd->last_arg);
+		cfd->last_arg = NULL;
+		cfd->last_idx = 0;
+		return (i);
+	}
+}
+
 struct cls *
 CLS_New(cls_cbc_f *before, cls_cbc_f *after, unsigned maxlen)
 {




More information about the varnish-commit mailing list