diff --git a/data/wicd.glade b/data/wicd.glade index 40d2ca3..a5eea9f 100644 --- a/data/wicd.glade +++ b/data/wicd.glade @@ -1,6 +1,6 @@ - + 450 @@ -36,107 +36,33 @@ True True - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - network_menu - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Create Ad-Hoc Network + Create an ad-hoc network True - + - + True gtk-add - 1 - + True - Enable/Disable Interfaces + Enter a hidden network to try to locate. + Find a hidden network True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - Enable Wired Interface - True - - - - True - gtk-yes - - - - - - - True - Enable Wireless Interface - True - - - - True - gtk-yes - - - - - - - True - Disable Wired Interface - True - - - - True - gtk-stop - - - - - - - True - Disable Wireless Interface - True - - - - True - gtk-stop - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Hidden Network - True - + - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - network-wireless + wicd @@ -468,7 +394,6 @@ Preferences 125 560 - . GDK_WINDOW_TYPE_HINT_DIALOG diff --git a/init/slackware/rc.wicd b/init/slackware/rc.wicd index 343051e..aef7d58 100755 --- a/init/slackware/rc.wicd +++ b/init/slackware/rc.wicd @@ -17,10 +17,6 @@ wicd_start() { else echo "Starting wicd daemon..." wicd 2>/dev/null 1>&2 - # Activate the pm-utils sleep hook - if [ ! -x /usr/lib/pm-utils/sleep.d/55wicd ]; then - chmod +x /usr/lib/pm-utils/sleep.d/55wicd - fi fi } @@ -32,11 +28,6 @@ wicd_stop() { else pkill -f python.*wicd-daemon.py 2>/dev/null fi - # Deactivate the pm-utils sleep hook - if [ -x /usr/lib/pm-utils/sleep.d/55wicd ]; then - chmod -x /usr/lib/pm-utils/sleep.d/55wicd - fi - } # See how we were called and take appropriate action diff --git a/wicd/autoconnect.py b/wicd/autoconnect.py index 546daf7..472a2d1 100755 --- a/wicd/autoconnect.py +++ b/wicd/autoconnect.py @@ -20,25 +20,23 @@ import dbus import time import gobject +import sys from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) bus = dbus.SystemBus() proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon') daemon = dbus.Interface(proxy_obj, 'org.wicd.daemon') +loop = gobject.MainLoop() -def reply_handle(): - loop.quit() -def error_handle(e): + +def handler(*args): loop.quit() print daemon.Hello() time.sleep(3) daemon.SetSuspend(False) if not daemon.CheckIfConnecting(): - print daemon.AutoConnect(True, reply_handler=reply_handle, - error_handler=error_handle) daemon.SetForcedDisconnect(False) - -loop = gobject.MainLoop() -loop.run() + daemon.AutoConnect(True, reply_handler=handler, error_handler=handler) + diff --git a/wicd/backends/be-external.py b/wicd/backends/be-external.py index 024e0fa..801574d 100644 --- a/wicd/backends/be-external.py +++ b/wicd/backends/be-external.py @@ -98,6 +98,10 @@ def GetWiredInterfaces(*args, **kargs): """ Call the wnettools GetWiredInterfaces method. """ return wnettools.GetWiredInterfaces(*args, **kargs) +def IsValidWpaSuppDriver(*args, **kargs): + """ Call the wnettools IsValidWpaSuppDrive method. """ + return wnettools.IsValidWpaSuppDriver(*args, **kargs) + def NeedsExternalCalls(*args, **kargs): """ Return True, since this backend using iwconfig/ifconfig. """ return True diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index 18c1a94..b8d22ec 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -102,6 +102,10 @@ def GetWiredInterfaces(*args, **kargs): """ Call the wnettools GetWiredInterfaces method. """ return wnettools.GetWiredInterfaces(*args, **kargs) +def IsValidWpaSuppDriver(*args, **kargs): + """ Call the wnettools IsValidWpaSuppDrive method. """ + return wnettools.IsValidWpaSuppDriver(*args, **kargs) + def get_iw_ioctl_result(iface, call): """ Makes the given ioctl call and returns the results. diff --git a/wicd/configmanager.py b/wicd/configmanager.py index d688506..2b130a9 100644 --- a/wicd/configmanager.py +++ b/wicd/configmanager.py @@ -24,15 +24,15 @@ reusable for other purposes as well. # along with this program. If not, see . # -from ConfigParser import ConfigParser +from ConfigParser import RawConfigParser from wicd.misc import stringToNone -class ConfigManager(ConfigParser): +class ConfigManager(RawConfigParser): """ A class that can be used to manage a given configuration file. """ def __init__(self, path): - ConfigParser.__init__(self) + RawConfigParser.__init__(self) self.config_file = path self.read(path) @@ -58,7 +58,7 @@ class ConfigManager(ConfigParser): if not self.has_section(section): self.add_section(section) - ConfigParser.set(self, section, str(option), str(value)) + RawConfigParser.set(self, section, str(option), str(value)) if save: self.write() @@ -66,7 +66,7 @@ class ConfigManager(ConfigParser): """ Calls the set_option method. """ self.set_option(*args, **kargs) - def get_option(self, section, option, default=None): + def get_option(self, section, option, default="__None__"): """ Wrapper around ConfigParser.get. Automatically adds any missing sections, adds the ability @@ -78,14 +78,17 @@ class ConfigManager(ConfigParser): self.add_section(section) if self.has_option(section, option): - ret = ConfigParser.get(self, section, option) + ret = RawConfigParser.get(self, section, option) if default: print ''.join(['found ', option, ' in configuration ', ret]) else: - print ''.join(['did not find ', option, + if default != "__None__": + print ''.join(['did not find ', option, ' in configuration, setting default ', str(default)]) - self.set(section, option, str(default), save=True) - ret = default + self.set(section, option, str(default), save=True) + ret = default + else: + ret = None # Try to intelligently handle the type of the return value. try: @@ -101,7 +104,7 @@ class ConfigManager(ConfigParser): def write(self): """ Writes the loaded config file to disk. """ configfile = open(self.config_file, 'w') - ConfigParser.write(self, configfile) + RawConfigParser.write(self, configfile) configfile.close() def remove_section(self,section): @@ -112,4 +115,7 @@ class ConfigManager(ConfigParser): """ if self.has_section(section): - ConfigParser.remove_section(self, section) + RawConfigParser.remove_section(self, section) + + def reload(self): + self.read(self.config_file) diff --git a/wicd/configscript.py b/wicd/configscript.py index 43845e1..9e1a7c5 100755 --- a/wicd/configscript.py +++ b/wicd/configscript.py @@ -122,6 +122,7 @@ def write_scripts(network, network_type, script_info): con.set(network, "afterscript", script_info["post_entry"]) con.set(network, "disconnectscript", script_info["disconnect_entry"]) con.write(open(wired_conf, "w")) + wired.ReloadConfig() wired.ReadWiredNetworkProfile(network) wired.SaveWiredNetworkProfile(network) else: @@ -133,9 +134,11 @@ def write_scripts(network, network_type, script_info): con.set(bssid, "afterscript", script_info["post_entry"]) con.set(bssid, "disconnectscript", script_info["disconnect_entry"]) con.write(open(wireless_conf, "w")) + wireless.ReloadConfig() wireless.ReadWirelessNetworkProfile(int(network)) wireless.SaveWirelessNetworkProfile(int(network)) + def main (argv): """ Runs the script configuration dialog. """ if len(argv) < 2: diff --git a/wicd/gui.py b/wicd/gui.py index 6b69fea..9ecb8f6 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -52,45 +52,62 @@ except: proxy_obj = daemon = wireless = wired = bus = None language = misc.get_language_list_gui() +DBUS_AVAIL = False -def setup_dbus(): - global bus, daemon, wireless, wired - +def setup_dbus(force=True): + global bus, daemon, wireless, wired, DBUS_AVAIL try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - error(None, "Could not connect to wicd's D-Bus interface. " + - "Make sure the daemon is started.") - sys.exit(1) - + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] wireless = dbus_ifaces['wireless'] wired = dbus_ifaces['wired'] + DBUS_AVAIL = True return True - -def error(parent, message): + +def handle_no_dbus(from_tray=False): + global DBUS_AVAIL + DBUS_AVAIL = False + if from_tray: return False + print "Wicd daemon is shutting down!" + error(None, language['lost_dbus'], block=False) + return False + +def error(parent, message, block=True): """ Shows an error dialog """ + def delete_event(dialog, id): + dialog.destroy() dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK) dialog.set_markup(message) - dialog.run() - dialog.destroy() + if not block: + dialog.present() + dialog.connect("response", delete_event) + else: + dialog.run() + dialog.destroy() def alert(parent, message): - """ Shows an error dialog """ + """ Shows an warning dialog """ dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK) dialog.set_markup(message) - dialog.run() - dialog.destroy() + dialog.present() + dialog.connect("response", lambda *args: dialog.destroy()) def dummy(x=None):pass @@ -215,7 +232,7 @@ class appGui(object): """ Initializes everything needed for the GUI. """ setup_dbus() - gladefile = wpath.share + "wicd.glade" + gladefile = os.path.join(wpath.share, "wicd.glade") self.wTree = gtk.glade.XML(gladefile) self.window = self.wTree.get_widget("window1") size = daemon.ReadWindowSize("main") @@ -232,10 +249,10 @@ class appGui(object): "disconnect_clicked" : self.disconnect_all, "main_exit" : self.exit, "cancel_clicked" : self.cancel_connect, - "connect_clicked" : self.connect_hidden, + "hidden_clicked" : self.connect_hidden, "preferences_clicked" : self.settings_dialog, "about_clicked" : self.about_dialog, - "create_adhoc_network_button_button" : self.create_adhoc_network, + "create_adhoc_clicked" : self.create_adhoc_network, } self.wTree.signal_autoconnect(dic) @@ -253,12 +270,13 @@ class appGui(object): self.status_area.hide_all() - if os.path.exists(wpath.images + "wicd.png"): - self.window.set_icon_from_file(wpath.images + "wicd.png") + if os.path.exists(os.path.join(wpath.images, "wicd.png")): + self.window.set_icon_from_file(os.path.join(wpath.images, "wicd.png")) self.statusID = None self.first_dialog_load = True self.is_visible = True self.pulse_active = False + self.pref = None self.standalone = standalone self.wpadrivercombo = None self.connecting = False @@ -277,7 +295,11 @@ class appGui(object): 'org.wicd.daemon.wireless') bus.add_signal_receiver(self.update_connect_buttons, 'StatusChanged', 'org.wicd.daemon') - bus.add_signal_receiver(setup_dbus, "DaemonClosing", "org.wicd.daemon") + if standalone: + bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", + "org.wicd.daemon") + bus.add_signal_receiver(lambda: setup_dbus(force=False), + "DaemonStarting", "org.wicd.daemon") try: gobject.timeout_add_seconds(1, self.update_statusbar) except: @@ -357,10 +379,14 @@ class appGui(object): def settings_dialog(self, widget, event=None): """ Displays a general settings dialog. """ - pref = PreferencesDialog(self.wTree, dbusmanager.get_dbus_ifaces()) - if pref.run() == 1: - pref.save_results() - pref.hide() + if not self.pref: + self.pref = PreferencesDialog(self.wTree, + dbusmanager.get_dbus_ifaces()) + else: + self.pref.load_preferences_diag() + if self.pref.run() == 1: + self.pref.save_results() + self.pref.hide() def connect_hidden(self, widget): """ Prompts the user for a hidden network, then scans for it. """ @@ -465,6 +491,7 @@ class appGui(object): current network state is the same as the previous. """ + if not DBUS_AVAIL: return if not state: state, x = daemon.GetConnectionStatus() @@ -520,15 +547,18 @@ class appGui(object): This method is called after a wireless scan is completed. """ + if not DBUS_AVAIL: return if not self.connecting: gobject.idle_add(self.refresh_networks, None, False, None) def dbus_scan_started(self): """ Called when a wireless scan starts. """ + if not DBUS_AVAIL: return self.network_list.set_sensitive(False) def refresh_clicked(self, widget=None): """ Kick off an asynchronous wireless scan. """ + if not DBUS_AVAIL: return self.refreshing = True wireless.Scan(reply_handler=None, error_handler=None) diff --git a/wicd/misc.py b/wicd/misc.py index 2c46ec1..a65fc4e 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -69,7 +69,7 @@ def Run(cmd, include_stderr=False, return_pipe=False): one output string from the command. """ - if type(cmd) is not list: + if not isinstance(cmd, list): cmd = to_unicode(str(cmd)) cmd = cmd.split() if include_stderr: @@ -82,8 +82,12 @@ def Run(cmd, include_stderr=False, return_pipe=False): tmpenv = os.environ.copy() tmpenv["LC_ALL"] = "C" tmpenv["LANG"] = "C" - f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, cwd='/', - env=tmpenv) + try: + f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, + cwd='/', env=tmpenv) + except OSError, e: + print "Running command %s failed: %s" % (str(cmd), str(e)) + return "" if return_pipe: return f.stdout @@ -383,7 +387,7 @@ def find_path(cmd): the file can not be found. """ - paths = os.getenv("PATH", default=["/usr/bin", "/usr/local/bin"]).split(':') + paths = os.getenv("PATH", default="/usr/bin:/usr/local/bin").split(':') for path in paths: if os.access(os.path.join(path, cmd), os.F_OK): return os.path.join(path, cmd) @@ -507,6 +511,7 @@ def get_language_list_gui(): language['cannot_start_daemon'] = _("Unable to connect to wicd daemon DBus interface." + \ "This typically means there was a problem starting the daemon." + \ "Check the wicd log for more info") + language['lost_dbus'] = _("The wicd daemon has shut down, the UI will not function properly until it is restarted.") return language @@ -531,6 +536,8 @@ def get_language_list_tray(): language['cannot_start_daemon'] = _("Unable to connect to wicd daemon DBus interface." + \ "This typically means there was a problem starting the daemon." + \ "Check the wicd log for more info") + language['no_daemon_tooltip'] = _("Wicd daemon unreachable") + language['lost_dbus'] = _("The wicd daemon has shut down, the UI will not function properly until it is restarted.") return language def noneToBlankString(text): diff --git a/wicd/networking.py b/wicd/networking.py index 11adcbf..b20be29 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -528,6 +528,11 @@ class Wireless(Controller): """ Get the out of iwconfig. """ return self.wiface.GetIwconfig() + def GetWpaSupplicantDrivers(self, drivers): + """ Returns all valid wpa_supplicant drivers in a list. """ + return [driver for driver in drivers if + BACKEND.IsValidWpaSuppDriver(driver)] + def IsUp(self): """ Calls the IsUp method for the wireless interface. diff --git a/wicd/prefs.py b/wicd/prefs.py index e4761c0..95a517f 100644 --- a/wicd/prefs.py +++ b/wicd/prefs.py @@ -27,8 +27,11 @@ handles recieving/sendings the settings from/to the daemon. import gtk import gobject import pango +import os +import gtk.glade from wicd import misc +from wicd import wpath from wicd.misc import checkboxTextboxToggle, noneToBlankString daemon = None @@ -53,85 +56,28 @@ class PreferencesDialog(object): wireless = dbus['wireless'] wired = dbus['wired'] self.wTree = wTree + self.wpadrivers = None self.prep_settings_diag() - self.build_preferences_diag() + self.load_preferences_diag() - def build_preferences_diag(self): - """ Builds the preferences dialog window. """ - def build_combobox(lbl): - """ Sets up a ComboBox using the given widget name. """ - liststore = gtk.ListStore(gobject.TYPE_STRING) - combobox = self.wTree.get_widget(lbl) - combobox.clear() - combobox.set_model(liststore) - cell = gtk.CellRendererText() - combobox.pack_start(cell, True) - combobox.add_attribute(cell, 'text', 0) - return combobox + def load_preferences_diag(self): + """ Loads data into the preferences Dialog. """ - def setup_label(name, lbl=""): - """ Sets up a label for the given widget name. """ - widget = self.wTree.get_widget(name) - if lbl: - widget.set_label(language[lbl]) - return widget - - self.dialog = self.wTree.get_widget("pref_dialog") - self.dialog.set_title(language['preferences']) - size = daemon.ReadWindowSize("pref") - width = size[0] - height = size[1] - if width > -1 and height > -1: - self.dialog.resize(int(width), int(height)) - else: - self.dialog.resize(gtk.gdk.screen_width() / 3, - gtk.gdk.screen_height() / 2) - - self.wiredcheckbox = setup_label("pref_always_check", - 'wired_always_on') self.wiredcheckbox.set_active(daemon.GetAlwaysShowWiredInterface()) - self.reconnectcheckbox = setup_label("pref_auto_check", - 'auto_reconnect') self.reconnectcheckbox.set_active(daemon.GetAutoReconnect()) - self.debugmodecheckbox = setup_label("pref_debug_check", - 'use_debug_mode') self.debugmodecheckbox.set_active(daemon.GetDebugMode()) - self.displaytypecheckbox = setup_label("pref_dbm_check", - 'display_type_dialog') self.displaytypecheckbox.set_active(daemon.GetSignalDisplayType()) - self.usedefaultradiobutton = setup_label("pref_use_def_radio", - 'use_default_profile') - self.showlistradiobutton = setup_label("pref_prompt_radio", - 'show_wired_list') - self.lastusedradiobutton = setup_label("pref_use_last_radio", - 'use_last_used_profile') - # DHCP Clients - self.dhcpautoradio = setup_label("dhcp_auto_radio", "wicd_auto_config") - self.dhclientradio = self.wTree.get_widget("dhclient_radio") - self.pumpradio = self.wTree.get_widget("pump_radio") - self.dhcpcdradio = self.wTree.get_widget("dhcpcd_radio") dhcp_list = [self.dhcpautoradio, self.dhclientradio, self.dhcpcdradio, self.pumpradio] - dhcp_method = daemon.GetDHCPClient() dhcp_list[dhcp_method].set_active(True) - # Wired Link Detection Apps - self.linkautoradio = setup_label("link_auto_radio", 'wicd_auto_config') - self.linkautoradio = setup_label("link_auto_radio") - self.ethtoolradio = setup_label("ethtool_radio") - self.miitoolradio = setup_label("miitool_radio") wired_link_list = [self.linkautoradio, self.ethtoolradio, self.miitoolradio] wired_link_method = daemon.GetLinkDetectionTool() wired_link_list[wired_link_method].set_active(True) - - # Route Flushing Apps - self.flushautoradio = setup_label("flush_auto_radio", - 'wicd_auto_config') - self.ipflushradio = setup_label("ip_flush_radio") - self.routeflushradio = setup_label("route_flush_radio") + flush_list = [self.flushautoradio, self.ipflushradio, self.routeflushradio] flush_method = daemon.GetFlushTool() @@ -145,16 +91,9 @@ class PreferencesDialog(object): elif auto_conn_meth == 3: self.lastusedradiobutton.set_active(True) - self.entryWirelessInterface = self.wTree.get_widget("pref_wifi_entry") self.entryWirelessInterface.set_text(daemon.GetWirelessInterface()) - - self.entryWiredInterface = self.wTree.get_widget("pref_wired_entry") self.entryWiredInterface.set_text(daemon.GetWiredInterface()) - # Replacement for the combo box hack - self.wpadrivercombo = build_combobox("pref_wpa_combobox") - self.wpadrivers = ["wext", "hostap", "madwifi", "atmel", "ndiswrapper", - "ipw", "ralink legacy"] found = False def_driver = daemon.GetWPADriver() for i, x in enumerate(self.wpadrivers): @@ -172,14 +111,6 @@ class PreferencesDialog(object): # Use wext as default, since normally it is the correct driver. self.wpadrivercombo.set_active(0) - # Set up global DNS stuff - self.useGlobalDNSCheckbox = setup_label("pref_global_check", - 'use_global_dns') - self.searchDomEntry = self.wTree.get_widget("pref_search_dom_entry") - self.dns1Entry = self.wTree.get_widget("pref_dns1_entry") - self.dns2Entry = self.wTree.get_widget("pref_dns2_entry") - self.dns3Entry = self.wTree.get_widget("pref_dns3_entry") - self.useGlobalDNSCheckbox.connect("toggled", checkboxTextboxToggle, (self.dns1Entry, self.dns2Entry, self.dns3Entry, self.searchDomEntry)) @@ -198,7 +129,6 @@ class PreferencesDialog(object): self.dns3Entry.set_sensitive(False) # Load backend combobox - self.backendcombo = build_combobox("pref_backend_combobox") self.backends = daemon.GetBackendList() # "" is included as a hack for DBus limitations, so we remove it. self.backends.remove("") @@ -226,9 +156,12 @@ class PreferencesDialog(object): """ Hides the preferences dialog window. """ self.dialog.hide() + def destroy(self): + self.dialog.destroy() + def show_all(self): """ Shows the preferences dialog window. """ - self.show_all() + self.dialog.show() def save_results(self): """ Pushes the selected settings to the daemon. """ @@ -287,6 +220,24 @@ class PreferencesDialog(object): def prep_settings_diag(self): """ Set up anything that doesn't have to be persisted later. """ + def build_combobox(lbl): + """ Sets up a ComboBox using the given widget name. """ + liststore = gtk.ListStore(gobject.TYPE_STRING) + combobox = self.wTree.get_widget(lbl) + combobox.clear() + combobox.set_model(liststore) + cell = gtk.CellRendererText() + combobox.pack_start(cell, True) + combobox.add_attribute(cell, 'text', 0) + return combobox + + def setup_label(name, lbl=""): + """ Sets up a label for the given widget name. """ + widget = self.wTree.get_widget(name) + if lbl: + widget.set_label(language[lbl]) + return widget + # External Programs tab self.wTree.get_widget("gen_settings_label").set_label(language["gen_settings"]) self.wTree.get_widget("ext_prog_label").set_label(language["ext_programs"]) @@ -309,3 +260,71 @@ class PreferencesDialog(object): self.set_label("pref_wifi_label", "%s:" % language['wireless_interface']) self.set_label("pref_wired_label", "%s:" % language['wired_interface']) self.set_label("pref_driver_label", "%s:" % language['wpa_supplicant_driver']) + + self.dialog = self.wTree.get_widget("pref_dialog") + self.dialog.set_title(language['preferences']) + if os.path.exists(os.path.join(wpath.images, "wicd.png")): + self.dialog.set_icon_from_file(os.path.join(wpath.images, "wicd.png")) + size = daemon.ReadWindowSize("pref") + width = size[0] + height = size[1] + if width > -1 and height > -1: + self.dialog.resize(int(width), int(height)) + else: + self.dialog.resize(gtk.gdk.screen_width() / 3, + gtk.gdk.screen_height() / 2) + + self.wiredcheckbox = setup_label("pref_always_check", + 'wired_always_on') + + self.reconnectcheckbox = setup_label("pref_auto_check", + 'auto_reconnect') + self.debugmodecheckbox = setup_label("pref_debug_check", + 'use_debug_mode') + self.displaytypecheckbox = setup_label("pref_dbm_check", + 'display_type_dialog') + self.usedefaultradiobutton = setup_label("pref_use_def_radio", + 'use_default_profile') + self.showlistradiobutton = setup_label("pref_prompt_radio", + 'show_wired_list') + self.lastusedradiobutton = setup_label("pref_use_last_radio", + 'use_last_used_profile') + + + # DHCP Clients + self.dhcpautoradio = setup_label("dhcp_auto_radio", "wicd_auto_config") + self.dhclientradio = self.wTree.get_widget("dhclient_radio") + self.pumpradio = self.wTree.get_widget("pump_radio") + self.dhcpcdradio = self.wTree.get_widget("dhcpcd_radio") + + # Wired Link Detection Apps + self.linkautoradio = setup_label("link_auto_radio", 'wicd_auto_config') + self.linkautoradio = setup_label("link_auto_radio") + self.ethtoolradio = setup_label("ethtool_radio") + self.miitoolradio = setup_label("miitool_radio") + + # Route Flushing Apps + self.flushautoradio = setup_label("flush_auto_radio", + 'wicd_auto_config') + self.ipflushradio = setup_label("ip_flush_radio") + self.routeflushradio = setup_label("route_flush_radio") + + # Replacement for the combo box hack + self.wpadrivercombo = build_combobox("pref_wpa_combobox") + self.wpadrivers = ["wext", "hostap", "madwifi", "atmel", + "ndiswrapper", "ipw"] + self.wpadrivers = wireless.GetWpaSupplicantDrivers(self.wpadrivers) + self.wpadrivers.append("ralink_legacy") + + self.entryWirelessInterface = self.wTree.get_widget("pref_wifi_entry") + self.entryWiredInterface = self.wTree.get_widget("pref_wired_entry") + + # Set up global DNS stuff + self.useGlobalDNSCheckbox = setup_label("pref_global_check", + 'use_global_dns') + self.searchDomEntry = self.wTree.get_widget("pref_search_dom_entry") + self.dns1Entry = self.wTree.get_widget("pref_dns1_entry") + self.dns2Entry = self.wTree.get_widget("pref_dns2_entry") + self.dns3Entry = self.wTree.get_widget("pref_dns3_entry") + + self.backendcombo = build_combobox("pref_backend_combobox") \ No newline at end of file diff --git a/wicd/wicd-client.py b/wicd/wicd-client.py index c403141..40114de 100755 --- a/wicd/wicd-client.py +++ b/wicd/wicd-client.py @@ -59,7 +59,7 @@ if not hasattr(gtk, "StatusIcon"): import egg.trayicon USE_EGG = True except ImportError: - print 'Unable to load tray icon: Missing egg.trayicon module.' + print 'Unable to load tray icon: Missing both egg.trayicon and gtk.StatusIcon modules.' ICON_AVAIL = False misc.RenameProcess("wicd-client") @@ -125,7 +125,11 @@ class TrayIcon(object): self.max_snd_gain = 10000 self.max_rcv_gain = 10000 self.animate = animate - self.update_tray_icon() + if DBUS_AVAIL: + self.update_tray_icon() + else: + handle_no_dbus() + self.set_not_connected_state() def wired_profile_chooser(self): """ Launch the wired profile chooser. """ @@ -135,7 +139,7 @@ class TrayIcon(object): def set_wired_state(self, info): """ Sets the icon info for a wired state. """ wired_ip = info[0] - self.tr.set_from_file(wpath.images + "wired.png") + self.tr.set_from_file(os.path.join(wpath.images, "wired.png")) self.tr.set_tooltip(language['connected_to_wired'].replace('$A', wired_ip)) @@ -165,12 +169,14 @@ class TrayIcon(object): cur_network = info[1] self.tr.set_tooltip(language['connecting'] + " to " + cur_network + "...") - self.tr.set_from_file(wpath.images + "no-signal.png") + self.tr.set_from_file(os.path.join(wpath.images, "no-signal.png")) - def set_not_connected_state(self, info): + def set_not_connected_state(self, info=None): """ Set the icon info for the not connected state. """ self.tr.set_from_file(wpath.images + "no-signal.png") - if wireless.GetKillSwitchEnabled(): + if not DBUS_AVAIL: + status = language['no_daemon_tooltip'] + elif wireless.GetKillSwitchEnabled(): status = (language['not_connected'] + " (" + language['killswitch_enabled'] + ")") else: @@ -179,7 +185,7 @@ class TrayIcon(object): def update_tray_icon(self, state=None, info=None): """ Updates the tray icon and current connection status. """ - if not self.use_tray: return False + if not self.use_tray or not DBUS_AVAIL: return False if not state or not info: [state, info] = daemon.GetConnectionStatus() @@ -342,22 +348,15 @@ class TrayIcon(object): def tray_scan_started(self): """ Callback for when a wireless scan is started. """ + if not DBUS_AVAIL: return self._is_scanning = True self.init_network_menu() def tray_scan_ended(self): """ Callback for when a wireless scan finishes. """ + if not DBUS_AVAIL: return self._is_scanning = False self.populate_network_menu() - - def dbus_lost(self): - """ Callback for when the daemon is going down. """ - global DBUS_AVAIL - print "The daemon is going down!!" - DBUS_AVAIL = False - time.sleep(1) - while not setup_dbus(): - time.sleep(20) def on_activate(self, data=None): """ Opens the wicd GUI. """ @@ -474,6 +473,9 @@ class TrayIcon(object): net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/") submenu = net_menuitem.get_submenu() self._clear_menu(submenu) + if not DBUS_AVAIL: + net_menuitem.show() + return is_connecting = daemon.CheckIfConnecting() num_networks = wireless.GetNumberOfNetworks() @@ -638,26 +640,42 @@ Arguments: \t-a\t--no-animate\tRun the tray without network traffic tray animations. """ -def setup_dbus(): - global daemon, wireless, wired, DBUS_AVAIL - +def setup_dbus(force=True): + global bus, daemon, wireless, wired, DBUS_AVAIL + print "Connecting to daemon..." try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - gui.error(None, language['cannot_start_daemon']) - sys.exit(1) + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + gui.error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False + + bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] wireless = dbus_ifaces['wireless'] wired = dbus_ifaces['wired'] DBUS_AVAIL = True + print "Connected." + return True +def handle_no_dbus(): + global DBUS_AVAIL + DBUS_AVAIL = False + gui.handle_no_dbus(from_tray=True) + print "Wicd daemon is shutting down!" + gui.error(None, language['lost_dbus'], block=False) + return False + def main(argv): """ The main frontend program. @@ -702,7 +720,7 @@ def main(argv): # Check to see if wired profile chooser was called before icon # was launched (typically happens on startup or daemon restart). - if daemon.GetNeedWiredProfileChooser(): + if DBUS_AVAIL and daemon.GetNeedWiredProfileChooser(): daemon.SetNeedWiredProfileChooser(False) tray_icon.icon_info.wired_profile_chooser() @@ -715,9 +733,11 @@ def main(argv): 'org.wicd.daemon.wireless') bus.add_signal_receiver(tray_icon.tr.tray_scan_started, 'SendStartScanSignal', 'org.wicd.daemon.wireless') - bus.add_signal_receiver(tray_icon.tr.dbus_lost, + bus.add_signal_receiver(lambda: handle_no_dbus() or tray_icon.icon_info.set_not_connected_state(), "DaemonClosing", 'org.wicd.daemon') - print 'Done.' + bus.add_signal_receiver(lambda: setup_dbus(force=False), "DaemonStarting", + "org.wicd.daemon") + print 'Done loading.' mainloop = gobject.MainLoop() mainloop.run() diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index d40ee8a..150d81e 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -113,7 +113,8 @@ class WicdDaemon(dbus.service.Object): self.wired.wiface = self.wifi.wiface signal.signal(signal.SIGTERM, self.DaemonClosing) - + self.DaemonStarting() + # Scan since we just got started if auto_connect: print "autoconnecting if needed...", str(self.GetWirelessInterface()) @@ -705,6 +706,11 @@ class WicdDaemon(dbus.service.Object): print 'calling wired profile chooser' self.SetNeedWiredProfileChooser(True) + @dbus.service.signal(dbus_interface="org.wicd.daemon", signature='') + def DaemonStarting(self): + """ Emits a signa indicating the daemon is starting. """ + pass + @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='') def DaemonClosing(self): """ Emits a signal indicating the daemon will be closing. """ @@ -1066,7 +1072,8 @@ class WirelessDaemon(dbus.service.Object): def SaveWirelessNetworkProfile(self, id): """ Writes a wireless profile to disk. """ def write_script_ent(prof, script): - self.config.set(prof, script, None) + if not self.config.has_option(prof, script): + self.config.set(prof, script, None) cur_network = self.LastScan[id] bssid_key = cur_network["bssid"] @@ -1088,12 +1095,12 @@ class WirelessDaemon(dbus.service.Object): write_script_ent(bssid_key, "beforescript") write_script_ent(bssid_key, "afterscript") - write_script_ent(bssid_key, "disconnect") + write_script_ent(bssid_key, "disconnectscript") if cur_network["use_settings_globally"]: write_script_ent(essid_key, "beforescript") write_script_ent(essid_key, "afterscript") - write_script_ent(essid_key, "disconnect") + write_script_ent(essid_key, "disconnectscript") self.config.write() @@ -1120,7 +1127,17 @@ class WirelessDaemon(dbus.service.Object): """ Removes the global entry for the networkid provided. """ essid_key = "essid:" + str(self.LastScan[networkid]) self.config.remove_section(essid_key) - + + @dbus.service.method('org.wicd.daemon.wireless') + def GetWpaSupplicantDrivers(self, drivers): + """ Returns all valid wpa_supplicant drivers in a given list. """ + return self.wifi.GetWpaSupplicantDrivers(drivers) + + @dbus.service.method('org.wicd.daemon.wireless') + def ReloadConfig(self): + """ Reloads the active config file. """ + self.config.reload() + @dbus.service.signal(dbus_interface='org.wicd.daemon.wireless', signature='') def SendStartScanSignal(self): """ Emits a signal announcing a scan has started. """ @@ -1395,6 +1412,11 @@ class WiredDaemon(dbus.service.Object): if not sections: sections = [""] return sections + + @dbus.service.method('org.wicd.daemon.wired') + def ReloadConfig(self): + """ Reloads the active config file. """ + self.config.reload() def usage(): @@ -1529,10 +1551,11 @@ def main(argv): daemon = WicdDaemon(wicd_bus, auto_connect=auto_connect) gobject.threads_init() if not no_poll: - (child_pid, x, x, x) = gobject.spawn_async(["/usr/bin/python", "-O", - wpath.lib + "monitor.py"], - flags=gobject.SPAWN_CHILD_INHERITS_STDIN) - signal.signal(signal.SIGTERM, sigterm_caught) + (child_pid, x, x, x) = gobject.spawn_async( + [misc.find_path("python"), "-O", os.path.join(wpath.lib, "monitor.py")], + flags=gobject.SPAWN_CHILD_INHERITS_STDIN + ) + signal.signal(signal.SIGTERM, sigterm_caught) # Enter the main loop mainloop = gobject.MainLoop() @@ -1546,8 +1569,12 @@ def main(argv): def sigterm_caught(sig=None, frame=None): """ Called when a SIGTERM is caught, kills monitor.py before exiting. """ global child_pid - print 'Daemon going down, killing wicd-monitor...' - os.kill(child_pid, signal.SIGTERM) + if child_pid: + print 'Daemon going down, killing wicd-monitor...' + try: + os.kill(child_pid, signal.SIGTERM) + except OSError: + pass print 'Removing PID file...' if os.path.exists(wpath.pidfile): os.remove(wpath.pidfile) diff --git a/wicd/wnettools.py b/wicd/wnettools.py index a9ff211..0a0b9c2 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -131,6 +131,16 @@ def NeedsExternalCalls(): """ Returns True if the backend needs to use an external program. """ raise NotImplementedError + +def IsValidWpaSuppDriver(driver): + """ Returns True if given string is a valid wpa_supplicant driver. """ + output = misc.Run(["wpa_supplicant", "-D%s" % driver, "-iwlan9", + "-c/etc/zzzzzzzz.confzzz"]) + if re.match("Unsupported driver", output): + return False + else: + return True + class BaseInterface(object): """ Control a network interface. """ @@ -752,7 +762,7 @@ class BaseWirelessInterface(BaseInterface): """ if not self.iface: return False cmd = ['iwconfig', self.iface, 'essid', essid] - if channel: + if channel and str(channel).isdigit(): cmd.extend(['channel', str(channel)]) if bssid: cmd.extend(['ap', bssid]) @@ -770,7 +780,8 @@ class BaseWirelessInterface(BaseInterface): if not wpa_pass_path: return None key_pattern = re.compile('network={.*?\spsk=(.*?)\n}.*', re.I | re.M | re.S) - cmd = ' '.join([wpa_pass_path, network['essid'], network['key']]) + cmd = [wpa_pass_path, network['essid'], network['key']] + if self.verbose: print cmd return misc.RunRegex(key_pattern, misc.Run(cmd)) def Authenticate(self, network): @@ -784,9 +795,10 @@ class BaseWirelessInterface(BaseInterface): if self.wpa_driver == RALINK_DRIVER: self._AuthenticateRalinkLegacy(network) else: - cmd = ''.join(['wpa_supplicant -B -i ', self.iface, ' -c ', - wpath.networks, network['bssid'].replace(':','').lower(), - ' -D ', self.wpa_driver]) + cmd = ['wpa_supplicant', '-B', '-i', self.iface, '-c', + os.path.join(wpath.networks, + network['bssid'].replace(':', '').lower()), + '-D', self.wpa_driver] if self.verbose: print cmd misc.Run(cmd)