[netfilter-cvslog] r4331 - trunk/nfsim/core

rusty at netfilter.org rusty at netfilter.org
Sat Oct 8 19:34:06 CEST 2005


Author: rusty at netfilter.org
Date: 2005-10-08 19:34:03 +0200 (Sat, 08 Oct 2005)
New Revision: 4331

Modified:
   trunk/nfsim/core/core.c
   trunk/nfsim/core/tui.c
   trunk/nfsim/core/tui.h
   trunk/nfsim/core/utils.c
Log:
Merge Max Kellerman's backtick expansion (partially rewritten).
Use explicit extension path to find extensions (none exist yet).  Assume they will go under tools/extensions/ in the source tree, and in /usr/lib/nfsim/.
Ensure that "line" arg to process_line is a talloc pointer: hang temporary allocations off it.  Also ensure that argv[] is a talloc ptr for tools to use.



Modified: trunk/nfsim/core/core.c
===================================================================
--- trunk/nfsim/core/core.c	2005-10-08 17:04:51 UTC (rev 4330)
+++ trunk/nfsim/core/core.c	2005-10-08 17:34:03 UTC (rev 4331)
@@ -451,6 +451,7 @@
 		setenv("LD_LIBRARY_PATH", path, 1);
 		talloc_free(path);
 		module_path = talloc_asprintf(NULL, "%s/nfsim", LIBDIR);
+		extension_path = module_path;
 	} else {
 		char *oldpath, *path;
 
@@ -463,11 +464,13 @@
 		talloc_free(path);
 		module_path = talloc_asprintf(NULL, "%.*s/netfilter/ipv4",
 					      (int)(p - argv[0]), argv[0]);
+		extension_path = talloc_asprintf(NULL, "%.*s/tools/extensions",
+					      (int)(p - argv[0]), argv[0]);
 	}
-	if (getenv("NFSIM_MODPATH")) {
-		talloc_free(module_path);
+	if (getenv("NFSIM_MODPATH"))
 		module_path = getenv("NFSIM_MODPATH");
-	}
+	if (getenv("NFSIM_EXTPATH"))
+		extension_path = getenv("NFSIM_EXTPATH");
 
 	/* Don't do failures during initialization. */
 	suppress_failtest++;

Modified: trunk/nfsim/core/tui.c
===================================================================
--- trunk/nfsim/core/tui.c	2005-10-08 17:04:51 UTC (rev 4330)
+++ trunk/nfsim/core/tui.c	2005-10-08 17:34:03 UTC (rev 4331)
@@ -25,6 +25,8 @@
 #include "expect.h"
 #include "utils.h"
 
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <stdio.h>
 #include <readline/readline.h>
 #include <readline/history.h>
@@ -35,6 +37,7 @@
 int tui_abort_on_fail;
 int tui_quiet;
 int tui_linenum = 1;
+char *extension_path;
 static bool stop;
 
 struct command {
@@ -222,47 +225,155 @@
 	return false;
 }
 
-static void process_line(char *line)
+/**
+ * backslash-escape a binary data block into a newly allocated
+ * string
+ *
+ * @param src a pointer to the data block
+ * @param src_len the length of the data block
+ * @return NULL if out of memory, or a pointer to the allocated escaped
+ *    string, which is terminated with a '\0' character
+ */
+static char *escape(const char *src, size_t src_len)
 {
-	int argc, prevspace;
-	char *argv[TUI_MAX_ARGS+1], quotemode;
+	static const char hexbuf[]= "0123456789abcdef";
+	char *dest, *p;
+	size_t i;
 
-	prevspace = 1;
-	quotemode = 0;
-	argc = 0;
+	/* src_len * 4 is always safe, it's the longest escape
+	   sequence for all characters */
+	dest = talloc_array(src, char, src_len * 4 + 1);
+	p = dest;
 
+	for (i = 0; i < src_len; i++) {
+		if (src[i] == '\n') {
+			*p++ = '\\';
+			*p++ = 'n';
+		} else if (src[i] == '\r') {
+			*p++ = '\\';
+			*p++ = 'r';
+		} else if (src[i] == '\0') {
+			*p++ = '\\';
+			*p++ = '0';
+		} else if (src[i] == '\t') {
+			*p++ = '\\';
+			*p++ = 't';
+		} else if (src[i] == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (src[i] & 0x80 || (src[i] & 0xe0) == 0) {
+			*p++ = '\\';
+			*p++ = 'x';
+			*p++ = hexbuf[(src[i] >> 4) & 0xf];
+			*p++ = hexbuf[src[i] & 0xf];
+		} else
+			*p++ = src[i];
+	}
+
+	*p++ = 0;
+	return dest;
+}
+
+/* Process `command`. */
+static char *backquote(char *line, unsigned int *off)
+{
+	char *end, *cmdstr, *str;
+	FILE *cmdfile;
+	size_t used, len, i;
+	int status;
+
+	/* Skip first backquote, look for next one. */
+	(*off)++;
+	end = strchr(line + *off, '`');
+	if (!end)
+		script_fail("no matching \"`\" found");
+
+	len = end - (line + *off);
+	cmdstr = talloc_asprintf(line, "%s/%.*s",
+				 extension_path, len, line + *off);
+	cmdfile = popen(cmdstr, "r");
+	if (!cmdfile)
+		script_fail("failed to popen '%s': %s\n",
+			    cmdstr, strerror(errno));
+
+	/* Jump over tail backquote. */
+	*off += len + 1;
+
+	/* Read command output. */
+	used = 0;
+	len = 1024;
+	str = talloc_array(line, char, len);
+
+	while ((i = fread(str + used, 1, len - used, cmdfile)) != 0) {
+		used += i;
+		if (used == len) {
+			if (len > 1024*1024)
+				script_fail("command '%s' output too long\n",
+					    cmdstr);
+			len *= 2;
+			str = talloc_realloc(line, str, char, len);
+		}
+	}
+	status = pclose(cmdfile);
+	if (status == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
+		script_fail("command '%s' failed\n", cmdstr);
+
+	return escape(str, used);
+}
+
+static void process_line(char *line, unsigned int off)
+{
+	unsigned int argc, i;
+	bool prevspace = true;
+	char **argv;
+
 	if (tui_echo_commands)
 		printf("%u:%s\n", tui_linenum, line);
 
-	/* FIXME: only handles quotes at the beginning and end of args */
-	while (*line) {
-		if (isspace(*line)) {
-			*line = 0;
-			prevspace = 1;
+	/* Talloc argv off line so commands can use it for auto-cleanup. */
+	argv = talloc_array(line, char *, TUI_MAX_ARGS+1);
+	argc = 0;
+	for (i = off; line[i]; i++) {
+		if (isspace(line[i])) {
+			line[i] = '\0';
+			prevspace = true;
+		} else if (*line == '`') {
+			/* FIXME: Assumes ` forms arg by itself. */
+			argv[argc++] = backquote(line, &i);
 		} else if (prevspace) {
-			argv[argc++] = line;
-			prevspace = 0;
+			/* If it is a comment, stop before we process `` */
+			if (argc == 0 && line[i] == '#')
+				goto out;
+			argv[argc++] = line+i;
+			prevspace = false;
 		}
-		line++;
 	}
 
-	if (argc > 0 && *argv[0] != '#') {
+	if (argc > 0) {
 		argv[argc] = NULL;
 		tui_do_command(argc, argv, tui_abort_on_fail);
 	}
+
+out:
 	tui_linenum++;
 	return;
 }
 
 static void readline_process_line(char *line)
 {
+	char *talloc_line; 
 	if (!line) {
 		stop = true;
 		return;
 	}
 
 	add_history(line);
-	process_line(line);
+
+	/* Readline isn't talloc-aware, so copy string: functions can
+	 * hang temporary variables off this. */
+	talloc_line = talloc_strdup(NULL, line);
+	process_line(talloc_line, 0);
+	talloc_free(talloc_line);
 }
 
 static void run_whole_file(int fd)
@@ -277,7 +388,7 @@
 	for (p = file; p < file + size; p += len+1) {
 		len = strcspn(p, "\n");
 		p[len] = '\0';
-		process_line(p);
+		process_line(file, p - file);
 	}
 }
 

Modified: trunk/nfsim/core/tui.h
===================================================================
--- trunk/nfsim/core/tui.h	2005-10-08 17:04:51 UTC (rev 4330)
+++ trunk/nfsim/core/tui.h	2005-10-08 17:34:03 UTC (rev 4331)
@@ -48,5 +48,6 @@
 extern int tui_abort_on_fail;
 extern int tui_quiet;
 extern int tui_linenum;
+extern char *extension_path;
 
 #endif /* __HAVE_TUI_H */

Modified: trunk/nfsim/core/utils.c
===================================================================
--- trunk/nfsim/core/utils.c	2005-10-08 17:04:51 UTC (rev 4330)
+++ trunk/nfsim/core/utils.c	2005-10-08 17:34:03 UTC (rev 4331)
@@ -29,6 +29,7 @@
 
 #include "utils.h"
 #include "log.h"
+#include "talloc.h"
 
 void barf(const char *fmt, ...)
 {
@@ -68,16 +69,16 @@
 {
 	unsigned int max = 16384;
 	int ret;
-	void *buffer = malloc(max+1);
+	void *buffer = talloc_array(NULL, char, max+1);
 
 	*size = 0;
 	while ((ret = read(fd, buffer + *size, max - *size)) > 0) {
 		*size += ret;
 		if (*size == max)
-			buffer = realloc(buffer, max *= 2 + 1);
+			buffer = talloc_realloc(NULL, buffer, char, max*=2+1);
 	}
 	if (ret < 0) {
-		free(buffer);
+		talloc_free(buffer);
 		buffer = NULL;
 	}
 	return buffer;
@@ -85,5 +86,5 @@
 
 void release_file(void *data, unsigned long size)
 {
-	free(data);
+	talloc_free(data);
 }




More information about the netfilter-cvslog mailing list