summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/nftables.h2
-rw-r--r--src/erec.c8
-rw-r--r--src/libnftables.c48
-rw-r--r--src/scanner.l2
4 files changed, 54 insertions, 6 deletions
diff --git a/include/nftables.h b/include/nftables.h
index 7b633905..d6d9b9cc 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -128,6 +128,7 @@ struct nft_ctx {
struct scope *top_scope;
void *json_root;
json_t *json_echo;
+ const char *stdin_buf;
};
enum nftables_exit_codes {
@@ -175,6 +176,7 @@ enum input_descriptor_types {
INDESC_FILE,
INDESC_CLI,
INDESC_NETLINK,
+ INDESC_STDIN,
};
/**
diff --git a/src/erec.c b/src/erec.c
index 7c9165c2..32fb079f 100644
--- a/src/erec.c
+++ b/src/erec.c
@@ -101,10 +101,11 @@ void print_location(FILE *f, const struct input_descriptor *indesc,
iloc = &tmp->location;
}
}
- if (indesc->name != NULL)
+ if (indesc->type != INDESC_BUFFER && indesc->name) {
fprintf(f, "%s:%u:%u-%u: ", indesc->name,
loc->first_line, loc->first_column,
loc->last_column);
+ }
}
const char *line_location(const struct input_descriptor *indesc,
@@ -145,6 +146,11 @@ void erec_print(struct output_ctx *octx, const struct error_record *erec,
line = indesc->data;
*strchrnul(line, '\n') = '\0';
break;
+ case INDESC_STDIN:
+ line = indesc->data;
+ line += loc->line_offset;
+ *strchrnul(line, '\n') = '\0';
+ break;
case INDESC_FILE:
line = line_location(indesc, loc, buf, sizeof(buf));
break;
diff --git a/src/libnftables.c b/src/libnftables.c
index 7b9d7efa..e76f32ef 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -424,13 +424,14 @@ static const struct input_descriptor indesc_cmdline = {
};
static int nft_parse_bison_buffer(struct nft_ctx *nft, const char *buf,
- struct list_head *msgs, struct list_head *cmds)
+ struct list_head *msgs, struct list_head *cmds,
+ const struct input_descriptor *indesc)
{
int ret;
parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->scanner = scanner_init(nft->state);
- scanner_push_buffer(nft->scanner, &indesc_cmdline, buf);
+ scanner_push_buffer(nft->scanner, indesc, buf);
ret = nft_parse(nft, nft->scanner, nft->state);
if (ret != 0 || nft->state->nerrs > 0)
@@ -439,11 +440,42 @@ static int nft_parse_bison_buffer(struct nft_ctx *nft, const char *buf,
return 0;
}
+static char *stdin_to_buffer(void)
+{
+ unsigned int bufsiz = 16384, consumed = 0;
+ int numbytes;
+ char *buf;
+
+ buf = xmalloc(bufsiz);
+
+ numbytes = read(STDIN_FILENO, buf, bufsiz);
+ while (numbytes > 0) {
+ consumed += numbytes;
+ if (consumed == bufsiz) {
+ bufsiz *= 2;
+ buf = realloc(buf, bufsiz);
+ }
+ numbytes = read(STDIN_FILENO, buf + consumed, bufsiz - consumed);
+ }
+ buf[consumed] = '\0';
+
+ return buf;
+}
+
+static const struct input_descriptor indesc_stdin = {
+ .type = INDESC_STDIN,
+ .name = "/dev/stdin",
+};
+
static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename,
struct list_head *msgs, struct list_head *cmds)
{
int ret;
+ if (nft->stdin_buf)
+ return nft_parse_bison_buffer(nft, nft->stdin_buf, msgs, cmds,
+ &indesc_stdin);
+
parser_init(nft, nft->state, msgs, cmds, nft->top_scope);
nft->scanner = scanner_init(nft->state);
if (scanner_read_file(nft, filename, &internal_location) < 0)
@@ -510,7 +542,8 @@ int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf)
if (nft_output_json(&nft->output))
rc = nft_parse_json_buffer(nft, nlbuf, &msgs, &cmds);
if (rc == -EINVAL)
- rc = nft_parse_bison_buffer(nft, nlbuf, &msgs, &cmds);
+ rc = nft_parse_bison_buffer(nft, nlbuf, &msgs, &cmds,
+ &indesc_cmdline);
parser_rc = rc;
@@ -578,7 +611,7 @@ retry:
}
snprintf(buf + offset, bufsize - offset, "\n");
- rc = nft_parse_bison_buffer(ctx, buf, msgs, &cmds);
+ rc = nft_parse_bison_buffer(ctx, buf, msgs, &cmds, &indesc_cmdline);
assert(list_empty(&cmds));
/* Stash the buffer that contains the variable definitions and zap the
@@ -608,6 +641,10 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename)
if (!strcmp(filename, "-"))
filename = "/dev/stdin";
+ if (!strcmp(filename, "/dev/stdin") &&
+ !nft_output_json(&nft->output))
+ nft->stdin_buf = stdin_to_buffer();
+
rc = -EINVAL;
if (nft_output_json(&nft->output))
rc = nft_parse_json_filename(nft, filename, &msgs, &cmds);
@@ -656,5 +693,8 @@ err:
json_print_echo(nft);
if (rc)
nft_cache_release(&nft->cache);
+
+ xfree(nft->stdin_buf);
+
return rc;
}
diff --git a/src/scanner.l b/src/scanner.l
index f28bf315..7dcc45c2 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -1032,7 +1032,7 @@ void scanner_push_buffer(void *scanner, const struct input_descriptor *indesc,
new_indesc = xzalloc(sizeof(struct input_descriptor));
memcpy(new_indesc, indesc, sizeof(*new_indesc));
new_indesc->data = buffer;
- new_indesc->name = NULL;
+ new_indesc->name = xstrdup(indesc->name);
scanner_push_indesc(state, new_indesc);
b = yy_scan_string(buffer, scanner);