diff options
-rw-r--r-- | debian/control | 1 | ||||
-rw-r--r-- | etc/bash_completion.d/20vyatta-cfg | 32 | ||||
-rw-r--r-- | src/cli_new.c | 95 | ||||
-rw-r--r-- | src/cli_objects.c | 2 | ||||
-rw-r--r-- | src/cli_val.h | 1 | ||||
-rw-r--r-- | src/commit.c | 24 | ||||
-rw-r--r-- | templates/interfaces/ethernet/node.tag/address/node.def | 2 |
7 files changed, 136 insertions, 21 deletions
diff --git a/debian/control b/debian/control index 10e1156..0ebf92d 100644 --- a/debian/control +++ b/debian/control @@ -13,6 +13,7 @@ Depends: bash (>= 3.1), procps (>= 1:3.2.7-3), quagga, coreutils (>= 5.97-5.3), + vyatta-op, vyatta-config-migrate, dhcp3-client Suggests: util-linux (>= 2.13-5), diff --git a/etc/bash_completion.d/20vyatta-cfg b/etc/bash_completion.d/20vyatta-cfg index dc05cf1..78f2e0a 100644 --- a/etc/bash_completion.d/20vyatta-cfg +++ b/etc/bash_completion.d/20vyatta-cfg @@ -647,6 +647,17 @@ ENDCOMMENT vyatta_help_text="\\nNo help text available" } +generate_pipe_help () +{ + local -a hcomps=( "${_vyatta_pipe_completions[@]}" \ + "${_vyatta_pipe_noncompletions[@]}" ) + local -a hstrs=() + for comp in "${hcomps[@]}"; do + hstrs+=("$(_vyatta_pipe_help "$comp")") + done + generate_help_text hcomps hstrs +} + vyatta_config_complete () { local restore_shopts=$( shopt -p extglob nullglob | tr \\n \; ) @@ -660,6 +671,14 @@ vyatta_config_complete () vyatta_do_help=0 fi + # handle pipe + if _vyatta_pipe_completion "${COMP_WORDS[@]}"; then + generate_pipe_help + vyatta_completions=( "${_vyatta_pipe_completions[@]}" ) + vyatta_do_complete + return + fi + if (( ${#COMP_WORDS[@]} < 2 )); then declare -a hitems=( "commit" \ "delete" \ @@ -707,19 +726,6 @@ vyatta_config_complete () (( num_comp -= 1 )) fi - # handle pipe - if [ "${COMP_WORDS[$num_comp]}" == "|" ]; then - declare -a hitems=( "more" \ - ) - declare -a hstrs=( \ - "Paginate the output" \ - ) - generate_help_text hitems hstrs - vyatta_completions=( "${hitems[@]}" ) - vyatta_do_complete - return - fi - (( last_idx = num_comp - 1 )) comp_words=( ${COMP_WORDS[@]:1:$num_comp} ) diff --git a/src/cli_new.c b/src/cli_new.c index bbdde10..d4380d5 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -56,8 +56,13 @@ static int cond_format_lens[DOMAIN_TYPE] = 6 /* MACADDR_TYPE */ }; +struct __slist_t; + +typedef struct __slist_t { + struct __slist_t *next; +} slist_t; + static int cli_val_len; -static char *cli_val_alloc; static char *cli_val_ptr; static char *exe_string; @@ -82,6 +87,8 @@ static void free_reuse_list(void); void free_path(vtw_path *path); static void free_string(char *str); static vtw_node * get_node(void); +void subtract_values(char **lhs, const char *rhs); + static void scan_ipv6(char *val, unsigned int *parts); @@ -1515,7 +1522,6 @@ int get_value(char **valpp, vtw_path *pathp) readcnt = fread(valp, 1, statbuf.st_size, in); if (readcnt != statbuf.st_size) { my_free(valp); - cli_val_alloc = 0; err = "Error reading value file in [%s]\n"; goto bad_path; } @@ -1781,6 +1787,91 @@ boolean validate_value(vtw_def *def, char *cp) return ret; } +typedef struct __value_list { + slist_t link; + const char *value; +} value_list; + +static void delete_list(slist_t *head) +{ + while (head != NULL) { + slist_t *elem = head; + head = head->next; + my_free(elem); + } +} + +void subtract_values(char **lhs, const char *rhs) +{ + size_t length = 0; + const char *line = NULL; + char *rhs_copy = NULL, *res = NULL; + slist_t *head = NULL, *ptr = NULL; + slist_t *new_head = NULL, *new_ptr = NULL; + + if (lhs == NULL || *lhs == NULL || **lhs == '\0' || rhs == NULL || *rhs == '\0') + return; + + rhs_copy = my_malloc(strlen(rhs), "subtract_values rhs_copy"); + strcpy(rhs_copy, rhs); + + head = ptr = my_malloc(sizeof(slist_t), "subtract_values list1"); + memset(head, 0, sizeof(slist_t)); + + line = strtok(rhs_copy, "\n\r"); + while (line != NULL && *line != '\0') { + value_list *elem = NULL; + + elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem1"); + memset(elem, 0, sizeof(value_list)); + elem->value = line; + ptr->next = (slist_t *) elem; + ptr = ptr->next; + line = strtok(NULL, "\n\r"); + } + + new_head = new_ptr = my_malloc(sizeof(slist_t), "subtract_values list2"); + memset(new_head, 0, sizeof(slist_t)); + + line = strtok(*lhs, "\n\r"); + while (line != NULL && *line != '\0') { + value_list *elem = NULL; + + ptr = head; + while (ptr->next != NULL) { + elem = (value_list *) ptr->next; + if (strncmp(line, elem->value, strlen(line)) == 0) + break; + ptr = ptr->next; + } + if (ptr->next == NULL) { + elem = (value_list *) my_malloc(sizeof(value_list), "subtract_values elem2"); + memset(elem, 0, sizeof(value_list)); + elem->value = line; + new_ptr->next = elem; + new_ptr = new_ptr->next; + length += strlen(line) + 1; + } + line = strtok(NULL, "\n\r"); + } + + new_ptr = new_head->next; + res = (char *) my_malloc(length + 1, "subtract_values result"); + *res = '\0'; + while (new_ptr != NULL) { + strcat(res, ((value_list *) new_ptr)->value); + strcat(res, "\n"); + new_ptr = new_ptr->next; + } + + delete_list(head); + delete_list(new_head); + if (rhs_copy != NULL) + my_free(rhs_copy); + my_free(*lhs); + + *lhs = res; +} int cli_val_read(char *buf, int max_size) { diff --git a/src/cli_objects.c b/src/cli_objects.c index 9bb36f0..8f0f6fe 100644 --- a/src/cli_objects.c +++ b/src/cli_objects.c @@ -334,7 +334,7 @@ void init_paths(boolean for_commit) init_path(&m_path, startp); switch_path(get_f_seg_c_ptr()); m_path.print_offset = max_len; - }else + } else init_path(&m_path, mdirp); init_path(&t_path, tdirp); diff --git a/src/cli_val.h b/src/cli_val.h index 7383263..edbda41 100644 --- a/src/cli_val.h +++ b/src/cli_val.h @@ -171,6 +171,7 @@ extern void dump_tree(vtw_node *node, int lev); extern void dump_def(vtw_def *defp); extern boolean val_cmp(valstruct *left, valstruct *right, vtw_cond_e cond); extern void out_of_memory(void); +extern void subtract_values(char **lhs, const char *rhs); extern boolean validate_value(vtw_def *def, char *value); extern void internal_error(int line, char *file); diff --git a/src/commit.c b/src/commit.c index 3fa77c5..400328e 100644 --- a/src/commit.c +++ b/src/commit.c @@ -91,7 +91,7 @@ static boolean validate_dir_for_commit() def_present = TRUE; memset(&def, 0, sizeof(def)); #ifdef DEBUG1 - printf("Parsing definition\n"); + printf("Parsing definition %s\n", t_path.path); #endif if ((status = parse_def(&def, t_path.path, @@ -102,7 +102,7 @@ static boolean validate_dir_for_commit() } #ifdef DEBUG1 else - printf("No definition\n"); + printf("No definition %s\n", t_path.path); #endif pop_path(&t_path); /* for PUSH 1 */ @@ -156,11 +156,27 @@ static boolean validate_dir_for_commit() /* read it */ cp = NULL; status = get_value(&cp, &m_path); - if (status == VTWERR_OK){ + if (status == VTWERR_OK) { #ifdef DEBUG1 printf("Validating value |%s|\n" "for path %s\n", cp, m_path.path); #endif + + // multivalue has to be diff-ed with the pre-existing value. + // only the difference should be ran through the validation. + // Bug #2509 + if (def.multi) { + char *old_value = NULL; + switch_path(APATH); // temporarily switching to the active config path + status = get_value(&old_value, &m_path); + if (status == VTWERR_OK) { + subtract_values(&cp, old_value); + } + switch_path(CPATH); + if (old_value) + my_free(old_value); + } + status = validate_value(&def, cp); ret = ret && status; } @@ -232,7 +248,7 @@ static boolean validate_dir_for_commit() } if (def_present && def.tag) - pop_path(&t_path); /* for PUSH 3a */ + pop_path(&t_path); /* for PUSH 2a */ if (def_present) free_def(&def); #ifdef DEBUG diff --git a/templates/interfaces/ethernet/node.tag/address/node.def b/templates/interfaces/ethernet/node.tag/address/node.def index 9447c99..6cef105 100644 --- a/templates/interfaces/ethernet/node.tag/address/node.def +++ b/templates/interfaces/ethernet/node.tag/address/node.def @@ -2,5 +2,5 @@ multi: type: txt help: "Set IPv4 address and prefix for this interface" syntax: exec "/opt/vyatta/sbin/vyatta-interfaces.pl --valid-addr $(@) --dev $(../@)" -create: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-update $(@) --dev $(../@)"; "Error setting address $(@) on dev $(../@)" +update: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-update $(@) --dev $(../@)"; "Error setting address $(@) on dev $(../@)" delete: "sudo /opt/vyatta/sbin/vyatta-interfaces.pl --eth-addr-delete $(@) --dev $(../@)"; "Error deleting address $(@) on dev $(../@)" |