[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