ifupdown: code to deconstruct the state_list gracefully
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 6 Mar 2007 22:53:10 +0000 (22:53 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 6 Mar 2007 22:53:10 +0000 (22:53 -0000)
(patch by Gabriel L. Somlo <somlo@cmu.edu>)

include/libbb.h
libbb/llist.c
networking/ifupdown.c

index 4293ae2699f83c1eab3eb6de421dcb1661f33796..809d8446ad4c71e258ffef0e5388cca99213f629 100644 (file)
@@ -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);
 
index 0a5978a26905a1a1435e17bbd92f1779b6dfd487..2b34f762c0faa09b202a61d255a58db86e5e0da7 100644 (file)
@@ -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))
index ccebecd951f5af817eb77084fcd173ac08eb078a..c7cb85350d0adda959a74c5480348f23df379859 100644 (file)
@@ -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) {