📄 command.c
字号:
{ if (match_type < range_match) match_type = range_match; matched++; } } else if (CMD_IPV6 (str)) { if (cmd_ipv6_match (command) == exact_match) { if (match_type < ipv6_match) match_type = ipv6_match; matched++; } } else if (CMD_IPV6_PREFIX (str)) { if (cmd_ipv6_prefix_match (command) == exact_match) { if (match_type < ipv6_prefix_match) match_type = ipv6_prefix_match; matched++; } } else if (CMD_IPV4 (str)) { if (cmd_ipv4_match (command) == exact_match) { if (match_type < ipv4_match) match_type = ipv4_match; matched++; } } else if (CMD_IPV4_PREFIX (str)) { if (cmd_ipv4_prefix_match (command) == exact_match) { if (match_type < ipv4_prefix_match) match_type = ipv4_prefix_match; matched++; } } else if (CMD_OPTION (str) || CMD_VARIABLE (str)) { if (match_type < extend_match) match_type = extend_match; matched++; } else { if (strcmp (command, str) == 0) { match_type = exact_match; matched++; } } } if (! matched) vector_slot (v, i) = NULL; } } return match_type;}/* Check ambiguous match */intis_cmd_ambiguous (char *command, vector v, int index, enum match_type type){ int i; int j; char *str = NULL; struct cmd_element *cmd_element; char *matched = NULL; vector descvec; struct desc *desc; for (i = 0; i < vector_max (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { int match = 0; descvec = vector_slot (cmd_element->strvec, index); for (j = 0; j < vector_max (descvec); j++) { enum match_type ret; desc = vector_slot (descvec, j); str = desc->cmd; switch (type) { case exact_match: if (! (CMD_OPTION (str) || CMD_VARIABLE (str)) && strcmp (command, str) == 0) match++; break; case partly_match: if (! (CMD_OPTION (str) || CMD_VARIABLE (str)) && strncmp (command, str, strlen (command)) == 0) { if (matched && strcmp (matched, str) != 0) return 1; /* There is ambiguous match. */ else matched = str; match++; } break; case range_match: if (cmd_range_match (str, command)) { if (matched && strcmp (matched, str) != 0) return 1; else matched = str; match++; } break; case ipv6_match: if (CMD_IPV6 (str)) match++; break; case ipv6_prefix_match: if ((ret = cmd_ipv6_prefix_match (command)) != no_match) { if (ret == partly_match) return 2; /* There is incomplete match. */ match++; } break; case ipv4_match: if (CMD_IPV4 (str)) match++; break; case ipv4_prefix_match: if ((ret = cmd_ipv4_prefix_match (command)) != no_match) { if (ret == partly_match) return 2; /* There is incomplete match. */ match++; } break; case extend_match: if (CMD_OPTION (str) || CMD_VARIABLE (str)) match++; break; case no_match: default: break; } } if (! match) vector_slot (v, i) = NULL; } return 0;}/* If src matches dst return dst string, otherwise return NULL */char *cmd_entry_function (char *src, char *dst){ /* Skip variable arguments. */ if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) || CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst)) return NULL; /* In case of 'command \t', given src is NULL string. */ if (src == NULL) return dst; /* Matched with input string. */ if (strncmp (src, dst, strlen (src)) == 0) return dst; return NULL;}/* If src matches dst return dst string, otherwise return NULL *//* This version will return the dst string always if it is CMD_VARIABLE for '?' key processing */char *cmd_entry_function_desc (char *src, char *dst){ if (CMD_VARARG (dst)) return dst; if (CMD_RANGE (dst)) { if (cmd_range_match (dst, src)) return dst; else return NULL; } if (CMD_IPV6 (dst)) { if (cmd_ipv6_match (src)) return dst; else return NULL; } if (CMD_IPV6_PREFIX (dst)) { if (cmd_ipv6_prefix_match (src)) return dst; else return NULL; } if (CMD_IPV4 (dst)) { if (cmd_ipv4_match (src)) return dst; else return NULL; } if (CMD_IPV4_PREFIX (dst)) { if (cmd_ipv4_prefix_match (src)) return dst; else return NULL; } /* Optional or variable commands always match on '?' */ if (CMD_OPTION (dst) || CMD_VARIABLE (dst)) return dst; /* In case of 'command \t', given src is NULL string. */ if (src == NULL) return dst; if (strncmp (src, dst, strlen (src)) == 0) return dst; else return NULL;}/* Check same string element existence. If it isn't there return 1. */intcmd_unique_string (vector v, char *str){ int i; char *match; for (i = 0; i < vector_max (v); i++) if ((match = vector_slot (v, i)) != NULL) if (strcmp (match, str) == 0) return 0; return 1;}/* Compare string to description vector. If there is same string return 1 else return 0. */intdesc_unique_string (vector v, char *str){ int i; struct desc *desc; for (i = 0; i < vector_max (v); i++) if ((desc = vector_slot (v, i)) != NULL) if (strcmp (desc->cmd, str) == 0) return 1; return 0;}/* '?' describe command support. */vectorcmd_describe_command (vector vline, struct vty *vty, int *status){ int i; vector cmd_vector;#define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; int index; int ret; enum match_type match; char *command; static struct desc desc_cr = { "<cr>", "" }; /* Set index. */ index = vector_max (vline) - 1; /* Make copy vector of current node's command vector. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); /* Prepare match vector */ matchvec = vector_init (INIT_MATCHVEC_SIZE); /* Filter commands. */ /* Only words precedes current word will be checked in this loop. */ for (i = 0; i < index; i++) { command = vector_slot (vline, i); match = cmd_filter_by_completion (command, cmd_vector, i); if (match == vararg_match) { struct cmd_element *cmd_element; vector descvec; int j, k; for (j = 0; j < vector_max (cmd_vector); j++) if ((cmd_element = vector_slot (cmd_vector, j)) != NULL) { descvec = vector_slot (cmd_element->strvec, vector_max (cmd_element->strvec) - 1); for (k = 0; k < vector_max (descvec); k++) { struct desc *desc = vector_slot (descvec, k); vector_set (matchvec, desc); } } vector_set (matchvec, &desc_cr); vector_free (cmd_vector); return matchvec; } if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1) { vector_free (cmd_vector); *status = CMD_ERR_AMBIGUOUS; return NULL; } else if (ret == 2) { vector_free (cmd_vector); *status = CMD_ERR_NO_MATCH; return NULL; } } /* Prepare match vector */ /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */ /* Make sure that cmd_vector is filtered based on current word */ command = vector_slot (vline, index); if (command) match = cmd_filter_by_completion (command, cmd_vector, index); /* Make description vector. */ for (i = 0; i < vector_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) { char *string = NULL; vector strvec = cmd_element->strvec; /* if command is NULL, index may be equal to vector_max */ if (command && index >= vector_max (strvec)) vector_slot (cmd_vector, i) = NULL; else { /* Check if command is completed. */ if (command == NULL && index == vector_max (strvec)) { string = "<cr>"; if (! desc_unique_string (matchvec, string)) vector_set (matchvec, &desc_cr); } else { int j; vector descvec = vector_slot (strvec, index); struct desc *desc; for (j = 0; j < vector_max (descvec); j++) { desc = vector_slot (descvec, j); string = cmd_entry_function_desc (command, desc->cmd); if (string) { /* Uniqueness check */ if (! desc_unique_string (matchvec, string)) vector_set (matchvec, desc); } } } } } vector_free (cmd_vector); if (vector_slot (matchvec, 0) == NULL) { vector_free (matchvec); *status= CMD_ERR_NO_MATCH; } else *status = CMD_SUCCESS; return matchvec;}/* Check LCD of matched command. */intcmd_lcd (char **matched){ int i; int j; int lcd = -1; char *s1, *s2; char c1, c2; if (matched[0] == NULL || matched[1] == NULL) return 0; for (i = 1; matched[i] != NULL; i++) { s1 = matched[i - 1]; s2 = matched[i]; for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++) if (c1 != c2) break; if (lcd < 0) lcd = j; else { if (lcd > j) lcd = j; } } return lcd;}/* Command line completion support. */char **cmd_complete_command (vector vline, struct vty *vty, int *status){ int i; vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));#define INIT_MATCHVEC_SIZE 10 vector matchvec; struct cmd_element *cmd_element; int index = vector_max (vline) - 1; char **match_str; struct desc *desc; vector descvec; char *command; int lcd; /* First, filter by preceeding command string */ for (i = 0; i < index; i++) { enum match_type match; int ret; command = vector_slot (vline, i); /* First try completion match, if there is exactly match return 1 */ match = cmd_filter_by_completion (command, cmd_vector, i); /* If there is exact match then filter ambiguous match else check ambiguousness. */ if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1) { vector_free (cmd_vector); *status = CMD_ERR_AMBIGUOUS; return NULL; } /* else if (ret == 2) { vector_free (cmd_vector); *status = CMD_ERR_NO_MATCH; return NULL; } */ } /* Prepare match vector. */ matchvec = vector_init (INIT_MATCHVEC_SIZE); /* Now we got into completion */ for (i = 0; i < vector_max (cmd_vector); i++) if ((cmd_element = vector_slot (cmd_vector, i)) != NULL) { char *string; vector strvec = cmd_element->strvec; /* Check field length */ if (index >= vector_max (strvec)) vector_slot (cmd_vector, i) = NULL; else { int j; descvec = vector_slot (strvec, index); for (j = 0; j < vector_max (descvec); j++) { desc = vector_slot (descvec, j); if ((string = cmd_entry_function (vector_slot (vline, index), desc->cmd))) if (cmd_unique_string (matchvec, string)) vector_set (matchvec, XSTRDUP (MTYPE_TMP, string)); } } } /* We don't need cmd_vector any more. */ vector_free (cmd_vector); /* No matched command */ if (vector_slot (matchvec, 0) == NULL) { vector_free (matchvec); /* In case of 'command \t' pattern. Do you need '?' command at the end of the line. */ if (vector_slot (vline, index) == '\0') *status = CMD_ERR_NOTHING_TODO; else *status = CMD_ERR_NO_MATCH; return NULL; } /* Only one matched */ if (vector_slot (matchvec, 1) == NULL) { match_str = (char **) matchvec->index; vector_only_wrapper_free (matchvec); *status = CMD_COMPLETE_FULL_MATCH; return match_str; } /* Make it sure last element is NULL. */ vector_set (matchvec, NULL); /* Check LCD of matched strings. */ if (vector_slot (vline, index) != NULL) { lcd = cmd_lcd ((char **) matchvec->index); if (lcd) { int len = strlen (vector_slot (vline, index)); if (len < lcd) { char *lcdstr; lcdstr = XMALLOC (MTYPE_TMP, lcd + 1); memcpy (lcdstr, matchvec->index[0], lcd); lcdstr[lcd] = '\0'; /* match_str = (char **) &lcdstr; */ /* Free matchvec. */ for (i = 0; i < vector_max (matchvec); i++) { if (vector_slot (matchvec, i)) XFREE (MTYPE_TMP, vector_slot (matchvec, i)); } vector_free (matchvec); /* Make new matchvec. */ matchvec = vector_init (INIT_MATCHVEC_SIZE); vector_set (matchvec, lcdstr); match_str = (char **) matchvec->index; vector_only_wrapper_free (matchvec); *status = CMD_COMPLETE_MATCH; return match_str; } } } match_str = (char **) matchvec->index; vector_only_wrapper_free (matchvec); *status = CMD_COMPLETE_LIST_MATCH; return match_str;}/* Execute command by argument vline vector. */intcmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd){ int i; int index; vector cmd_vector; struct cmd_element *cmd_element; struct cmd_element *matched_element; unsigned int matched_count, incomplete_count; int argc; char *argv[CMD_ARGC_MAX]; enum match_type match = 0; int varflag; char *command; /* Make copy of command elements. */ cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); for (index = 0; index < vector_max (vline); index++) { int ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -