diff options
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/llist.c | 35 | ||||
-rw-r--r-- | networking/ifupdown.c | 21 |
3 files changed, 45 insertions, 12 deletions
diff --git a/include/libbb.h b/include/libbb.h index 4293ae269..809d8446a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -475,6 +475,7 @@ typedef struct llist_s { extern void llist_add_to(llist_t **old_head, void *data); extern void llist_add_to_end(llist_t **list_head, void *data); extern void *llist_pop(llist_t **elm); +extern void llist_unlink(llist_t **head, llist_t *elm); extern void llist_free(llist_t *elm, void (*freeit)(void *data)); extern llist_t* llist_rev(llist_t *list); diff --git a/libbb/llist.c b/libbb/llist.c index 0a5978a26..2b34f762c 100644 --- a/libbb/llist.c +++ b/libbb/llist.c @@ -45,21 +45,40 @@ void llist_add_to_end(llist_t ** list_head, void *data) /* Remove first element from the list and return it */ void *llist_pop(llist_t ** head) { - void *data; + void *data, *next; if (!*head) - data = *head; - else { - void *next = (*head)->link; + return NULL; - data = (*head)->data; - free(*head); - *head = next; - } + data = (*head)->data; + next = (*head)->link; + free(*head); + *head = next; return data; } +/* Unlink arbitrary given element from the list */ +void llist_unlink(llist_t **head, llist_t *elm) +{ + llist_t *crt; + + if (!(elm && *head)) + return; + + if (elm == *head) { + *head = (*head)->link; + return; + } + + for (crt = *head; crt; crt = crt->link) { + if (crt->link == elm) { + crt->link = elm->link; + return; + } + } +} + /* Recursively free all elements in the linked list. If freeit != NULL * call it on each datum in the list */ void llist_free(llist_t * elm, void (*freeit) (void *data)) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index ccebecd95..c7cb85350 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1091,6 +1091,7 @@ int ifupdown_main(int argc, char **argv) llist_t *state_list = NULL; llist_t *target_list = NULL; const char *interfaces = "/etc/network/interfaces"; + FILE *state_fp; int any_failures = 0; cmds = iface_down; @@ -1117,6 +1118,19 @@ int ifupdown_main(int argc, char **argv) startup_PATH = getenv("PATH"); if (!startup_PATH) startup_PATH = ""; + /* Read the previous state from the state file */ + state_fp = fopen_or_warn("/var/run/ifstate", "r"); + if (state_fp) { + char *start, *end_ptr; + while ((start = xmalloc_fgets(state_fp)) != NULL) { + /* We should only need to check for a single character */ + end_ptr = start + strcspn(start, " \t\n"); + *end_ptr = '\0'; + llist_add_to(&state_list, start); + } + fclose(state_fp); + } + /* Create a list of interfaces to work on */ if (DO_ALL) { if (cmds == iface_up) { @@ -1166,7 +1180,7 @@ int ifupdown_main(int argc, char **argv) } } else { /* ifdown */ - if (iface_state) { + if (!iface_state) { bb_error_msg("interface %s not configured", iface); continue; } @@ -1236,7 +1250,8 @@ int ifupdown_main(int argc, char **argv) iface_state->data = newiface; } } else { - /* Remove an interface from the linked list */ + /* Remove an interface from state_list */ + llist_unlink(&state_list, iface_state); free(llist_pop(&iface_state)); } } @@ -1244,8 +1259,6 @@ int ifupdown_main(int argc, char **argv) /* Actually write the new state */ if (!NO_ACT) { - FILE *state_fp; - state_fp = xfopen("/var/run/ifstate", "w"); while (state_list) { if (state_list->data) { |