Add KDE notification support.
[dhcpcd-ui] / src / dhcpcd-gtk / main.c
index 56e2959ae31cab260ddd2291dc758728dd986c10..249881f14257f54a7deb09ff0a6cb06375fd7f25 100644 (file)
@@ -56,7 +56,7 @@ struct watch {
 };
 static struct watch *watches;
 
-WI_SCAN *wi_scans;
+WI_SCANwi_scans;
 
 static gboolean dhcpcd_try_open(gpointer data);
 static gboolean dhcpcd_wpa_try_open(gpointer data);
@@ -67,12 +67,10 @@ wi_scan_find(DHCPCD_WI_SCAN *scan)
        WI_SCAN *w;
        DHCPCD_WI_SCAN *dw;
 
-       for (w = wi_scans; w; w = w->next) {
+       TAILQ_FOREACH(w, &wi_scans, next) {
                for (dw = w->scans; dw; dw = dw->next)
                        if (dw == scan)
-                               break;
-               if (dw)
-                       return w;
+                               return w;
        }
        return NULL;
 }
@@ -141,7 +139,7 @@ update_online(DHCPCD_CONNECTION *con, bool showif)
                        if (i->up)
                                ison = true;
                }
-               msg = dhcpcd_if_message(i);
+               msg = dhcpcd_if_message(i, NULL);
                if (msg) {
                        if (showif)
                                g_message("%s", msg);
@@ -158,6 +156,7 @@ update_online(DHCPCD_CONNECTION *con, bool showif)
 
        if (online != ison || carrier != iscarrier) {
                online = ison;
+               carrier = iscarrier;
                if (ani_timer != 0) {
                        g_source_remove(ani_timer);
                        ani_timer = 0;
@@ -233,48 +232,6 @@ notify(const char *title, const char *msg, const char *icon)
 #  define notify(a, b, c)
 #endif
 
-static void
-dhcpcd_status_cb(DHCPCD_CONNECTION *con, const char *status, _unused void *data)
-{
-       static char *last = NULL;
-       const char *msg;
-       bool refresh;
-       WI_SCAN *w;
-
-       g_message("Status changed to %s", status);
-       if (g_strcmp0(status, "down") == 0) {
-               msg = N_(last ?
-                   "Connection to dhcpcd lost" : "dhcpcd not running");
-               if (ani_timer != 0) {
-                       g_source_remove(ani_timer);
-                       ani_timer = 0;
-                       ani_counter = 0;
-               }
-               gtk_status_icon_set_from_icon_name(status_icon,
-                   "network-offline");
-               gtk_status_icon_set_tooltip_text(status_icon, msg);
-               notify(_("No network"), msg, "network-offline");
-               dhcpcd_prefs_abort();
-               while (wi_scans) {
-                       w = wi_scans->next;
-                       dhcpcd_wi_scans_free(wi_scans->scans);
-                       g_free(wi_scans);
-                       wi_scans = w;
-               }
-       } else {
-               if ((last == NULL || g_strcmp0(last, "down") == 0)) {
-                       g_message(_("Connected to %s-%s"), "dhcpcd",
-                           dhcpcd_version(con));
-                       refresh = true;
-               } else
-                       refresh = false;
-               update_online(con, refresh);
-       }
-
-       g_free(last);
-       last = g_strdup(status);
-}
-
 static struct watch *
 dhcpcd_findwatch(int fd, gpointer data, struct watch **last)
 {
@@ -360,6 +317,52 @@ dhcpcd_watch(int fd,
        return TRUE;
 }
 
+static void
+dhcpcd_status_cb(DHCPCD_CONNECTION *con, const char *status,
+    _unused void *data)
+{
+       static char *last = NULL;
+       const char *msg;
+       bool refresh;
+       WI_SCAN *w;
+
+       g_message("Status changed to %s", status);
+       if (g_strcmp0(status, "down") == 0) {
+               msg = N_(last ?
+                   "Connection to dhcpcd lost" : "dhcpcd not running");
+               if (ani_timer != 0) {
+                       g_source_remove(ani_timer);
+                       ani_timer = 0;
+                       ani_counter = 0;
+               }
+               online = carrier = false;
+               gtk_status_icon_set_from_icon_name(status_icon,
+                   "network-offline");
+               gtk_status_icon_set_tooltip_text(status_icon, msg);
+               prefs_abort();
+               menu_abort();
+               wpa_abort();
+               while ((w = TAILQ_FIRST(&wi_scans))) {
+                       TAILQ_REMOVE(&wi_scans, w, next);
+                       dhcpcd_wi_scans_free(w->scans);
+                       g_free(w);
+               }
+               dhcpcd_unwatch(-1, con);
+               g_timeout_add(DHCPCD_RETRYOPEN, dhcpcd_try_open, con);
+       } else {
+               if ((last == NULL || g_strcmp0(last, "down") == 0)) {
+                       g_message(_("Connected to %s-%s"), "dhcpcd",
+                           dhcpcd_version(con));
+                       refresh = true;
+               } else
+                       refresh = g_strcmp0(last, "opened") ? false : true;
+               update_online(con, refresh);
+       }
+
+       g_free(last);
+       last = g_strdup(status);
+}
+
 static gboolean
 dhcpcd_cb(_unused GIOChannel *gio, _unused GIOCondition c, gpointer data)
 {
@@ -385,19 +388,28 @@ dhcpcd_try_open(gpointer data)
        static int last_error;
 
        con = (DHCPCD_CONNECTION *)data;
-       fd = dhcpcd_open(con);
+       fd = dhcpcd_open(con, true);
        if (fd == -1) {
-               if (errno != last_error)
+               if (errno == EACCES || errno == EPERM) {
+                       if ((fd = dhcpcd_open(con, false)) != -1)
+                               goto unprived;
+               }
+               if (errno != last_error) {
                        g_critical("dhcpcd_open: %s", strerror(errno));
-               last_error = errno;
+                       last_error = errno;
+               }
                return TRUE;
        }
 
+unprived:
        if (!dhcpcd_watch(fd, dhcpcd_cb, con)) {
                dhcpcd_close(con);
                return TRUE;
        }
 
+       /* Start listening to WPA events */
+       dhcpcd_wpa_start(con);
+
        return FALSE;
 }
 
@@ -407,29 +419,32 @@ dhcpcd_if_cb(DHCPCD_IF *i, _unused void *data)
        DHCPCD_CONNECTION *con;
        char *msg;
        const char *icon;
+       bool new_msg;
+
+       /* We should ignore renew and stop so we don't annoy the user */
+       if (g_strcmp0(i->reason, "RENEW") &&
+           g_strcmp0(i->reason, "STOP") &&
+           g_strcmp0(i->reason, "STOPPED"))
+       {
+               msg = dhcpcd_if_message(i, &new_msg);
+               if (msg) {
+                       g_message("%s", msg);
+                       if (new_msg) {
+                               if (i->up)
+                                       icon = "network-transmit-receive";
+                               //else
+                               //      icon = "network-transmit";
+                               if (!i->up)
+                                       icon = "network-offline";
+                               notify(_("Network event"), msg, icon);
+                       }
+                       g_free(msg);
+               }
+       }
 
        /* Update the tooltip with connection information */
        con = dhcpcd_if_connection(i);
        update_online(con, false);
-
-       /* We should ignore renew and stop so we don't annoy the user */
-       if (g_strcmp0(i->reason, "RENEW") == 0 ||
-           g_strcmp0(i->reason, "STOP") == 0 ||
-           g_strcmp0(i->reason, "STOPPED") == 0)
-               return;
-
-       msg = dhcpcd_if_message(i);
-       if (msg) {
-               g_message("%s", msg);
-               if (i->up)
-                       icon = "network-transmit-receive";
-               //else
-               //      icon = "network-transmit";
-               if (!i->up)
-                       icon = "network-offline";
-               notify(_("Network event"), msg, icon);
-               g_free(msg);
-       }
 }
 
 static gboolean
@@ -513,14 +528,17 @@ dhcpcd_wpa_scan_cb(DHCPCD_WPA *wpa, _unused void *data)
        if (scans == NULL && errno)
                g_warning("%s: %s", i->ifname, strerror(errno));
        errno = lerrno;
-       for (w = wi_scans; w; w = w->next)
+       TAILQ_FOREACH(w, &wi_scans, next) {
                if (w->interface == i)
                        break;
+       }
        if (w == NULL) {
                w = g_malloc(sizeof(*w));
                w->interface = i;
-               w->next = wi_scans;
-               wi_scans = w;
+               w->scans = scans;
+               w->ifmenu = NULL;
+               TAILQ_INIT(&w->menus);
+               TAILQ_INSERT_TAIL(&wi_scans, w, next);
        } else {
                txt = NULL;
                msg = N_("New Access Point");
@@ -544,9 +562,19 @@ dhcpcd_wpa_scan_cb(DHCPCD_WPA *wpa, _unused void *data)
                        notify(msg, txt, "network-wireless");
                        g_free(txt);
                }
-               dhcpcd_wi_scans_free(w->scans);
+               menu_update_scans(w, scans);
        }
-       w->scans = scans;
+}
+
+static void
+dhcpcd_wpa_status_cb(DHCPCD_WPA *wpa, const char *status, _unused void *data)
+{
+       DHCPCD_IF *i;
+
+       i = dhcpcd_wpa_if(wpa);
+       g_message("%s: WPA status %s", i->ifname, status);
+       if (g_strcmp0(status, "down") == 0)
+               dhcpcd_unwatch(-1, wpa);
 }
 
 int
@@ -573,16 +601,18 @@ main(int argc, char *argv[])
        notify_init(PACKAGE);
 #endif
 
+       TAILQ_INIT(&wi_scans);
        g_message(_("Connecting ..."));
        con = dhcpcd_new();
        if (con ==  NULL) {
                g_critical("libdhcpcd: %s", strerror(errno));
                exit(EXIT_FAILURE);
        }
+       dhcpcd_set_progname(con, "dhcpcd-gtk");
        dhcpcd_set_status_callback(con, dhcpcd_status_cb, NULL);
        dhcpcd_set_if_callback(con, dhcpcd_if_cb, NULL);
        dhcpcd_wpa_set_scan_callback(con, dhcpcd_wpa_scan_cb, NULL);
-       //dhcpcd_wpa_set_status_callback(con, dhcpcd_wpa_status_cb, NULL);
+       dhcpcd_wpa_set_status_callback(con, dhcpcd_wpa_status_cb, NULL);
        if (dhcpcd_try_open(con))
                g_timeout_add(DHCPCD_RETRYOPEN, dhcpcd_try_open, con);