X-Git-Url: https://roy.marples.name/git diff --git a/prefs.c b/prefs.c index a56783f..dd293a9 100644 --- a/prefs.c +++ b/prefs.c @@ -24,158 +24,37 @@ * SUCH DAMAGE. */ -#include +#include +#include "dhcpcd-config.h" #include "dhcpcd-gtk.h" #include "prefs.h" +static GtkWidget *dialog, *blocks, *names, *controls, *clear, *rebind; +static GtkWidget *autoconf, *address, *router, *dns_servers, *dns_search; static GPtrArray *config; -static GtkWidget *dialog, *blocks, *names, *controls; -static GtkWidget *hostname, *fqdn, *clientid, *duid, *arp, *ipv4ll; +static char *block, *name; static void -free_config(GPtrArray **array) -{ - GPtrArray *a; - guint i; - GValueArray *c; - - a = *array; - if (a == NULL) - return; - for (i = 0; i < a->len; i++) { - c = g_ptr_array_index(a, i); - g_value_array_free(c); - } - g_ptr_array_free(a, TRUE); - *array = NULL; -} - -static GPtrArray * -read_config(const char *block, const char *name) -{ - GType otype; - GError *error; - GPtrArray *array; - - error = NULL; - otype = dbus_g_type_get_struct("GValueArray", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - otype = dbus_g_type_get_collection("GPtrArray", otype); - if (!dbus_g_proxy_call(dbus, "GetConfig", &error, - G_TYPE_STRING, block, G_TYPE_STRING, name, G_TYPE_INVALID, - otype, &array, G_TYPE_INVALID)) - { - g_critical("GetConfig: %s", error->message); - g_clear_error(&error); - return NULL; - } - return array; -} - -static gboolean -get_config(GPtrArray *array, const char *option, const char **value) -{ - guint i; - GValueArray *c; - GValue *val; - const char *str; - - if (array == NULL) - return FALSE; - for (i = 0; i < array->len; i++) { - c = g_ptr_array_index(array, i); - val = g_value_array_get_nth(c, 0); - str = g_value_get_string(val); - if (strcmp(str, option) != 0) - continue; - if (value != NULL) { - val = g_value_array_get_nth(c, 1); - str = g_value_get_string(val); - if (*str == '\0') - *value = NULL; - else - *value = str; - } - return TRUE; - } - if (value != NULL) - *value = NULL; - return FALSE; -} - -static gboolean -toggle_generic(gboolean has, const char *val) -{ - return (has && (val == NULL || g_strcmp0(val, "\"\"") == 0)); -} - -static gboolean -toggle_generic_neg(gboolean has, _unused const char *val) -{ - return !has; -} - -static gboolean -toggle_fqdn(gboolean has, const char *val) -{ - return (has && - (val == NULL || - g_strcmp0(val, "both") == 0 || - g_strcmp0(val, "ptr") == 0)); -} - -static void -set_check(GtkToggleButton *button, - GPtrArray *global, GPtrArray *conf, const char *name, - gboolean (*test)(gboolean, const char *)) +show_config(GPtrArray *array) { const char *val; - gboolean has, incons; - - if (get_config(conf, name, &val)) { - has = TRUE; - incons = FALSE; - } else if (global == NULL) { - incons = FALSE; - has = FALSE; - } else { - has = get_config(global, name, &val); - incons = TRUE; - } - gtk_toggle_button_set_active(button, test(has, val)); - gtk_toggle_button_set_inconsistent(button, incons); -} - -static void -show_config(const char *block, const char *name) -{ - GPtrArray *global; + bool autocnf; - if (block || name) - global = read_config(NULL, NULL); - else - global = NULL; - - free_config(&config); - config = read_config(block, name); - set_check(GTK_TOGGLE_BUTTON(hostname), global, config, - "hostname", toggle_generic); - set_check(GTK_TOGGLE_BUTTON(fqdn), global, config, - "fqdn", toggle_fqdn); - set_check(GTK_TOGGLE_BUTTON(clientid), global, config, - "clientid", toggle_generic); - set_check(GTK_TOGGLE_BUTTON(duid), global, config, - "duid", toggle_generic); - gtk_widget_set_sensitive(duid, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(clientid))); - set_check(GTK_TOGGLE_BUTTON(arp), global, config, - "noarp", toggle_generic_neg); - set_check(GTK_TOGGLE_BUTTON(ipv4ll), global, config, - "noipv4ll", toggle_generic_neg); - gtk_widget_set_sensitive(ipv4ll, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(arp))); - free_config(&global); + if (get_config_static(array, "ip_address=", &val) != -1) + autocnf = false; + else { + get_config(array, "inform", &val); + autocnf = true; + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autoconf), autocnf); + gtk_entry_set_text(GTK_ENTRY(address), val ? val : ""); + get_config_static(array, "routers=", &val); + gtk_entry_set_text(GTK_ENTRY(router), val ? val : ""); + get_config_static(array, "domain_name_servers=", &val); + gtk_entry_set_text(GTK_ENTRY(dns_servers), val ? val : ""); + get_config_static(array, "domain_search=", &val); + gtk_entry_set_text(GTK_ENTRY(dns_search), val ? val : ""); } static char * @@ -196,6 +75,59 @@ combo_active_text(GtkWidget *widget) return text; } +static void +make_config(GPtrArray *array) +{ + const char *val; + bool a; + + a = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(autoconf)); + val = gtk_entry_get_text(GTK_ENTRY(address)); + if (*val == '\0') + val = NULL; + set_option(array, false, "inform", a ? val : NULL); + set_option(array, true, "ip_address=", a ? NULL : val); + + val = gtk_entry_get_text(GTK_ENTRY(router)); + if (a && *val == '\0') + val = NULL; + set_option(array, true, "routers=", val); + + val = gtk_entry_get_text(GTK_ENTRY(dns_servers)); + if (a && *val == '\0') + val = NULL; + set_option(array, true, "domain_name_servers=", val); + + val = gtk_entry_get_text(GTK_ENTRY(dns_search)); + if (a && *val == '\0') + val = NULL; + set_option(array, true, "domain_search=", val); +} + +static void +set_name_active_icon(const char *iname) +{ + GtkListStore *store; + GtkTreeIter iter; + GtkIconTheme *it; + GtkTreePath *path; + GdkPixbuf *pb; + + store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(names))); + if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(names), &iter)) + return; + it = gtk_icon_theme_get_default(); + pb = gtk_icon_theme_load_icon(it, iname, + GTK_ICON_SIZE_MENU, 0, NULL); + if (pb) { + path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); + gtk_list_store_set(store, &iter, 0, pb, -1); + g_object_unref(pb); + gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); + gtk_tree_path_free(path); + } +} + static GSList * list_interfaces(void) { @@ -236,34 +168,35 @@ list_ssids(void) } static void -blocks_on_change(GtkWidget *widget, _unused gpointer data) +blocks_on_change(GtkWidget *widget) { GtkListStore *store; GtkTreeIter iter; GError *error; - char **list, **lp, *block; + char **list, **lp; const char *iname, *nn; GSList *l, *new_names; GtkIconTheme *it; GdkPixbuf *pb; - gint n; + int n; + if (name) { + make_config(config); + save_config(block, name, config); + free_config(&config); + show_config(config); + g_free(block); + g_free(name); + name = NULL; + } block = combo_active_text(widget); store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(names))); gtk_list_store_clear(store); - if (strcmp(block, "global") == 0) { - g_free(block); - gtk_widget_set_sensitive(names, FALSE); - gtk_widget_set_sensitive(controls, TRUE); - show_config(NULL, NULL); - return; - } error = NULL; if (!dbus_g_proxy_call(dbus, "GetConfigBlocks", &error, G_TYPE_STRING, block, G_TYPE_INVALID, G_TYPE_STRV, &list, G_TYPE_INVALID)) { - g_free(block); g_warning("GetConfigBlocks: %s", error->message); g_clear_error(&error); return; @@ -307,40 +240,149 @@ blocks_on_change(GtkWidget *widget, _unused gpointer data) n++; } gtk_widget_set_sensitive(names, n); - gtk_widget_set_sensitive(controls, FALSE); g_slist_free(new_names); g_strfreev(list); - g_free(block); } static void -names_on_change(GtkWidget *widget, _unused gpointer data) +names_on_change(void) +{ + + if (name) { + make_config(config); + save_config(block, name, config); + g_free(name); + } + name = combo_active_text(names); + free_config(&config); + config = load_config(block, name); + show_config(config); + gtk_widget_set_sensitive(controls, name ? true : false); + gtk_widget_set_sensitive(clear, name ? true : false); + gtk_widget_set_sensitive(rebind, name ? true : false); +} + +static bool +valid_address(const char *val, bool allow_cidr) +{ + char *addr, *p, *e; + struct in_addr in; + gint64 cidr; + bool retval; + + addr = g_strdup(val); + if (allow_cidr) { + p = strchr(addr, '/'); + if (p != NULL) { + *p++ = '\0'; + errno = 0; + e = NULL; + cidr = g_ascii_strtoll(p, &e, 10); + if (cidr < 0 || cidr > 32 || + errno != 0 || *e != '\0') + { + retval = false; + goto out; + } + } + } + retval = inet_aton(addr, &in) == 0 ? false : true; + +out: + g_free(addr); + return retval; +} + + +static bool +address_lost_focus(GtkEntry *entry) +{ + const char *val; + + val = gtk_entry_get_text(entry); + if (*val != '\0' && !valid_address(val, true)) + gtk_entry_set_text(entry, ""); + return false; +} + +static bool +entry_lost_focus(GtkEntry *entry) { - char *block, *name; - - block = combo_active_text(blocks); - name = combo_active_text(widget); - gtk_widget_set_sensitive(controls, TRUE); - show_config(block, name); - g_free(block); - g_free(name); + const char *val; + char **a, **p; + + val = gtk_entry_get_text(entry); + a = g_strsplit(val, " ", 0); + for (p = a; *p; p++) { + if (**p != '\0' && !valid_address(*p, false)) { + gtk_entry_set_text(entry, ""); + break; + } + } + g_strfreev(a); + return false; } static void -on_toggle(GtkWidget *widget, gpointer data) +on_clear(void) { - gboolean active; - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE); - if (data == NULL) - return; - active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - gtk_widget_set_sensitive(GTK_WIDGET((GtkWidget *)data), active); + free_config(&config); + config = g_ptr_array_new(); + if (save_config(block, name, config)) { + set_name_active_icon("document-new"); + show_config(config); + } +} + +static void +rebind_interface(const char *iface) +{ + GError *error; + + error = NULL; + if (!dbus_g_proxy_call(dbus, "Rebind", &error, + G_TYPE_STRING, iface, G_TYPE_INVALID, G_TYPE_INVALID)) + { + g_critical("Rebind: %s: %s", iface, error->message); + g_clear_error(&error); + } +} + +static void +on_rebind(void) +{ + GSList *l; + const struct if_msg *ifm; + + make_config(config); + if (save_config(block, name, config)) { + set_name_active_icon(config->len == 0 ? + "document-new" : "document-save"); + show_config(config); + if (g_strcmp0(block, "interface") == 0) + rebind_interface(name); + else { + for (l = interfaces; l; l = l->next) { + ifm = (const struct if_msg *)l->data; + if (g_strcmp0(ifm->ssid, name) == 0) + rebind_interface(ifm->ifname); + } + } + } } static void on_destroy(void) { + + if (name != NULL) { + make_config(config); + save_config(block, name, config); + g_free(block); + g_free(name); + block = name = NULL; + } free_config(&config); dialog = NULL; } @@ -348,30 +390,17 @@ on_destroy(void) void dhcpcd_prefs_close(void) { - if (dialog) { + + if (dialog != NULL) { gtk_widget_destroy(dialog); dialog = NULL; } } -static void -on_delete(void) -{ - char *block, *name; - - //delete_config(); - //save_config(); - block = combo_active_text(blocks); - name = combo_active_text(names); - show_config(name ? block : NULL, name); - g_free(block); - g_free(name); -} - void dhcpcd_prefs_show(void) { - GtkWidget *dialog_vbox, *hbox, *vbox, *label; + GtkWidget *dialog_vbox, *hbox, *vbox, *table, *w; GtkListStore *store; GtkTreeIter iter; GtkCellRenderer *rend; @@ -385,30 +414,26 @@ dhcpcd_prefs_show(void) } dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", on_destroy, NULL); + g_signal_connect(G_OBJECT(dialog), "destroy", on_destroy, NULL); gtk_window_set_title(GTK_WINDOW(dialog), _("dhcpcd preferences")); - gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_resizable(GTK_WINDOW(dialog), false); gtk_window_set_icon_name(GTK_WINDOW(dialog), "config-users"); gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_type_hint(GTK_WINDOW(dialog), - GDK_WINDOW_TYPE_HINT_DIALOG); + GDK_WINDOW_TYPE_HINT_DIALOG); - dialog_vbox = gtk_vbox_new(FALSE, 3); + dialog_vbox = gtk_vbox_new(false, 10); + gtk_container_set_border_width(GTK_CONTAINER(dialog), 10); gtk_container_add(GTK_CONTAINER(dialog), dialog_vbox); - hbox = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(dialog_vbox), hbox, FALSE, FALSE, 3); - label = gtk_label_new("Configuration block:"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3); + hbox = gtk_hbox_new(false, 0); + gtk_box_pack_start(GTK_BOX(dialog_vbox), hbox, false, false, 3); + w = gtk_label_new("Configure:"); + gtk_box_pack_start(GTK_BOX(hbox), w, false, false, 3); store = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); it = gtk_icon_theme_get_default(); error = NULL; - pb = gtk_icon_theme_load_icon(it, "config-users", - GTK_ICON_SIZE_MENU, 0, &error); - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, pb, 1, "global", -1); - g_object_unref(pb); pb = gtk_icon_theme_load_icon(it, "network-wired", GTK_ICON_SIZE_MENU, 0, &error); gtk_list_store_append(store, &iter); @@ -421,74 +446,101 @@ dhcpcd_prefs_show(void) g_object_unref(pb); blocks = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); rend = gtk_cell_renderer_pixbuf_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(blocks), rend, FALSE); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(blocks), rend, false); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(blocks), rend, "pixbuf", 0); rend = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(blocks), rend, TRUE); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(blocks), rend, true); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(blocks), rend, "text", 1); gtk_combo_box_set_active(GTK_COMBO_BOX(blocks), 0); - gtk_box_pack_start(GTK_BOX(hbox), blocks, FALSE, FALSE, 3); - label = gtk_label_new("Block name:"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3); + gtk_box_pack_start(GTK_BOX(hbox), blocks, false, false, 3); store = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); names = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); rend = gtk_cell_renderer_pixbuf_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(names), rend, FALSE); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(names), rend, false); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(names), rend, "pixbuf", 0); rend = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(names), rend, TRUE); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(names), rend, true); gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(names), rend, "text", 1); - gtk_widget_set_sensitive(names, FALSE); - gtk_box_pack_start(GTK_BOX(hbox), names, FALSE, FALSE, 3); - gtk_signal_connect(GTK_OBJECT(blocks), "changed", + gtk_widget_set_sensitive(names, false); + gtk_box_pack_start(GTK_BOX(hbox), names, false, false, 3); + g_signal_connect(G_OBJECT(blocks), "changed", G_CALLBACK(blocks_on_change), NULL); - gtk_signal_connect(GTK_OBJECT(names), "changed", + g_signal_connect(G_OBJECT(names), "changed", G_CALLBACK(names_on_change), NULL); - label = gtk_hseparator_new(); - gtk_box_pack_start(GTK_BOX(dialog_vbox), label, TRUE, FALSE, 3); - controls = gtk_hbox_new(FALSE, 10); - gtk_box_pack_start(GTK_BOX(dialog_vbox), controls, TRUE, TRUE, 0); - vbox = gtk_vbox_new(FALSE, 3); - gtk_box_pack_start(GTK_BOX(controls), vbox, FALSE, FALSE, 0); - hostname = gtk_check_button_new_with_label(_("Send Hostname")); - gtk_signal_connect(GTK_OBJECT(hostname), "toggled", - G_CALLBACK(on_toggle), NULL); - gtk_box_pack_start(GTK_BOX(vbox), hostname, FALSE, FALSE, 3); - fqdn = gtk_check_button_new_with_label(_("Send FQDN")); - gtk_signal_connect(GTK_OBJECT(fqdn), "toggled", - G_CALLBACK(on_toggle), NULL); - gtk_box_pack_start(GTK_BOX(vbox), fqdn, FALSE, FALSE, 3); - clientid = gtk_check_button_new_with_label(_("Send ClientID")); - gtk_box_pack_start(GTK_BOX(vbox), clientid, FALSE, FALSE, 3); - duid = gtk_check_button_new_with_label(_("Send DUID")); - gtk_signal_connect(GTK_OBJECT(clientid), "toggled", - G_CALLBACK(on_toggle), duid); - gtk_signal_connect(GTK_OBJECT(duid), "toggled", - G_CALLBACK(on_toggle), NULL); - gtk_box_pack_start(GTK_BOX(vbox), duid, FALSE, FALSE, 3); - arp = gtk_check_button_new_with_label(_("Enable ARP checking")); - gtk_box_pack_start(GTK_BOX(vbox), arp, FALSE, FALSE, 3); - ipv4ll = gtk_check_button_new_with_label(_("Enable Zeroconf")); - gtk_box_pack_start(GTK_BOX(vbox), ipv4ll, FALSE, FALSE, 3); - gtk_signal_connect(GTK_OBJECT(arp), "toggled", - G_CALLBACK(on_toggle), ipv4ll); - gtk_signal_connect(GTK_OBJECT(ipv4ll), "toggled", - G_CALLBACK(on_toggle), NULL); - - hbox = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(dialog_vbox), hbox, TRUE, TRUE, 3); - label = gtk_button_new_from_stock(GTK_STOCK_DELETE); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - gtk_signal_connect(GTK_OBJECT(label), "clicked", on_delete, NULL); - label = gtk_button_new_from_stock(GTK_STOCK_CLOSE); - gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0); - gtk_signal_connect(GTK_OBJECT(label), "clicked", - dhcpcd_prefs_close, NULL); - - show_config(NULL, NULL); + w = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(dialog_vbox), w, true, false, 3); + controls = gtk_vbox_new(false, 10); + gtk_widget_set_sensitive(controls, false); + gtk_box_pack_start(GTK_BOX(dialog_vbox), controls, true, true, 0); + vbox = gtk_vbox_new(false, 3); + gtk_box_pack_start(GTK_BOX(controls), vbox, false, false, 0); + autoconf = gtk_check_button_new_with_label( + _("Automatically configure empty options")); + gtk_box_pack_start(GTK_BOX(vbox), autoconf, false, false, 3); + table = gtk_table_new(6, 2, false); + gtk_box_pack_start(GTK_BOX(controls), table, false, false, 0); + +#define attach_label(a, b, c, d, e) \ + do { \ + gtk_misc_set_alignment(GTK_MISC(a), 0.0, 0.5); \ + gtk_table_attach(GTK_TABLE(table), a, b, c, d, e, \ + GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 3, 3); \ + } while (0) +#define attach_entry(a, b, c, d, e) \ + gtk_table_attach(GTK_TABLE(table), a, b, c, d, e, \ + GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 3, 3); + + w = gtk_label_new(_("IP Address:")); + address = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(address), 15); + g_signal_connect(G_OBJECT(address), "focus-out-event", + G_CALLBACK(address_lost_focus), NULL); + attach_label(w, 0, 1, 0, 1); + attach_entry(address, 1, 2, 0, 1); + + w = gtk_label_new(_("Router:")); + router = gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(router), 12); + g_signal_connect(G_OBJECT(router), "focus-out-event", + G_CALLBACK(entry_lost_focus), NULL); + attach_label(w, 0, 1, 2, 3); + attach_entry(router, 1, 2, 2, 3); + + w = gtk_label_new(_("DNS Servers:")); + dns_servers = gtk_entry_new(); + g_signal_connect(G_OBJECT(dns_servers), "focus-out-event", + G_CALLBACK(entry_lost_focus), NULL); + attach_label(w, 0, 1, 3, 4); + attach_entry(dns_servers, 1, 2, 3, 4); + + w = gtk_label_new(_("DNS Search:")); + dns_search = gtk_entry_new(); + attach_label(w, 0, 1, 4, 5); + attach_entry(dns_search, 1, 2, 4, 5); + + hbox = gtk_hbox_new(false, 10); + gtk_box_pack_start(GTK_BOX(dialog_vbox), hbox, true, true, 3); + clear = gtk_button_new_from_stock(GTK_STOCK_CLEAR); + gtk_widget_set_sensitive(clear, false); + gtk_box_pack_start(GTK_BOX(hbox), clear, false, false, 0); + g_signal_connect(G_OBJECT(clear), "clicked", on_clear, NULL); + rebind = gtk_button_new_with_mnemonic(_("_Rebind")); + gtk_widget_set_sensitive(rebind, false); + w = gtk_image_new_from_stock(GTK_STOCK_EXECUTE, + GTK_ICON_SIZE_BUTTON); + gtk_button_set_image(GTK_BUTTON(rebind), w); + gtk_box_pack_start(GTK_BOX(hbox), rebind, false, false, 0); + g_signal_connect(G_OBJECT(rebind), "clicked", on_rebind, NULL); + w = gtk_button_new_from_stock(GTK_STOCK_CLOSE); + gtk_box_pack_end(GTK_BOX(hbox), w, false, false, 0); + g_signal_connect(G_OBJECT(w), "clicked", + dhcpcd_prefs_close, NULL); + + blocks_on_change(blocks); + show_config(NULL); gtk_widget_show_all(dialog); }