When reading in config files and we have failures on multiple
lines actually note the actual failure lines and return them.
This fixes an issue where we stopped counting errors after
the first one and we got missleading line numbers that
did not correspond to the actual problem.
This is fixed:
sharpd@donna ~/frr> sudo /usr/lib/frr/pimd --log=stdout -A 127.0.0.1 -f /etc/frr/pimd.conf
2018/10/11 09:41:01 PIM: VRF Created: default(0)
2018/10/11 09:41:01 PIM: pim_vrf_enable: for default
2018/10/11 09:41:01 PIM: zclient_lookup_sched_now: zclient lookup immediate connection scheduled
2018/10/11 09:41:01 PIM: zclient_lookup_new: zclient lookup socket initialized
2018/10/11 09:41:01 PIM: pimd 6.1-dev starting: vty@2611
2018/10/11 09:41:01 PIM: [EC
100663304] ERROR: No such command on config line 2: inteface lo
2018/10/11 09:41:01 PIM: [EC
100663304] ERROR: No such command on config line 3: ip igmp
2018/10/11 09:41:01 PIM: [EC
100663304] ERROR: No such command on config line 4: ip igmp join 224.1.1.1 13.13.13.2
^C2018/10/11 09:45:09 PIM: Terminating on signal SIGINT
2018/10/11 09:45:09 PIM: VRF Deletion: default(0)
Fixes: #3161
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
* as to why no command could be executed.
*/
int command_config_read_one_line(struct vty *vty,
- const struct cmd_element **cmd, int use_daemon)
+ const struct cmd_element **cmd,
+ uint32_t line_num, int use_daemon)
{
vector vline;
int saved_node;
}
}
- if (ret != CMD_SUCCESS && ret != CMD_WARNING)
- memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ);
+ if (ret != CMD_SUCCESS && ret != CMD_WARNING) {
+ struct vty_error *ve = XCALLOC(MTYPE_TMP, sizeof(*ve));
+
+ memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ);
+ ve->line_num = line_num;
+ if (!vty->error)
+ vty->error = list_new();
+
+ listnode_add(vty->error, ve);
+ }
cmd_free_strvec(vline);
*line_num = 0;
while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
- if (!error_ret)
- ++(*line_num);
+ ++(*line_num);
- ret = command_config_read_one_line(vty, NULL, 0);
+ ret = command_config_read_one_line(vty, NULL, *line_num, 0);
if (ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_ERR_NOTHING_TODO)
extern const char *cmd_prompt(enum node_type);
extern int command_config_read_one_line(struct vty *vty,
const struct cmd_element **,
- int use_config_node);
+ uint32_t line_num, int use_config_node);
extern int config_from_file(struct vty *, FILE *, unsigned int *line_num);
extern enum node_type node_parent(enum node_type);
/*
new->lbuf = buffer_new(0);
new->obuf = buffer_new(0); /* Use default buffer size. */
new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ);
- new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ);
new->max = VTY_BUFSIZ;
return new;
#endif /* VTYSH */
}
+static void vty_error_delete(void *arg)
+{
+ struct vty_error *ve = arg;
+
+ XFREE(MTYPE_TMP, ve);
+}
+
/* Close vty interface. Warning: call this only from functions that
will be careful not to access the vty afterwards (since it has
now been freed). This is safest from top-level functions (called
if (vty->buf)
XFREE(MTYPE_VTY, vty->buf);
- if (vty->error_buf)
- XFREE(MTYPE_VTY, vty->error_buf);
+ if (vty->error) {
+ vty->error->del = vty_error_delete;
+ list_delete(&vty->error);
+ }
/* Check configure. */
vty_config_unlock(vty);
{
int ret;
struct vty *vty;
+ struct vty_error *ve;
+ struct listnode *node;
unsigned int line_num = 0;
vty = vty_new();
break;
}
- nl = strchr(vty->error_buf, '\n');
- if (nl)
- *nl = '\0';
- flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", message,
- line_num, vty->error_buf);
+ for (ALL_LIST_ELEMENTS_RO(vty->error, node, ve)) {
+ nl = strchr(ve->error_buf, '\n');
+ if (nl)
+ *nl = '\0';
+ flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s",
+ message, ve->line_num, ve->error_buf);
+ }
}
vty_close(vty);
#define VTY_BUFSIZ 4096
#define VTY_MAXHIST 20
+struct vty_error {
+ char error_buf[VTY_BUFSIZ];
+ uint32_t line_num;
+};
+
/* VTY struct. */
struct vty {
/* File descripter of this vty. */
char *buf;
/* Command input error buffer */
- char *error_buf;
+ struct list *error;
/* Command cursor point */
int cp;
while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
lineno++;
- ret = command_config_read_one_line(vty, &cmd, 1);
+ ret = command_config_read_one_line(vty, &cmd, lineno, 1);
switch (ret) {
case CMD_WARNING: