diff --git a/data/wicd.glade b/data/wicd.glade index dd69932..0fe8d7a 100644 --- a/data/wicd.glade +++ b/data/wicd.glade @@ -1,6 +1,6 @@ - + 450 @@ -895,7 +895,7 @@ is already active. True - 6 + 8 True @@ -961,7 +961,7 @@ is already active. True True - route + route 0 True True @@ -1125,6 +1125,92 @@ is already active. + + + True + 0 + <b>Graphical Sudo Application</b> + True + + + 6 + 7 + + + + + + True + 12 + + + True + + + True + True + Automatic (recommended) + 0 + True + True + + + False + + + + + True + True + gksudo + 0 + True + True + sudo_auto_radio + + + False + 1 + + + + + True + True + kdesu + 0 + True + True + sudo_auto_radio + + + False + 2 + + + + + True + True + ktsuss + 0 + True + True + sudo_auto_radio + + + False + 3 + + + + + + + 7 + 8 + + diff --git a/wicd/backends/be-external.py b/wicd/backends/be-external.py index 3a3dac3..b96880c 100644 --- a/wicd/backends/be-external.py +++ b/wicd/backends/be-external.py @@ -6,8 +6,6 @@ This module implements functions to control and obtain information from network interfaces. -def SetDNS() -- Set the DNS servers of the system. -def GetWirelessInterfaces() -- Get the wireless interfaces available. class Interface() -- Control a network interface. class WiredInterface() -- Control a wired network interface. class WirelessInterface() -- Control a wireless network interface. @@ -31,9 +29,9 @@ class WirelessInterface() -- Control a wireless network interface. # along with this program. If not, see . # -import wicd.misc as misc -import wicd.wnettools as wnettools - +from wicd import misc +from wicd import wnettools +from wicd.wnettools import * import re import os import os.path @@ -78,30 +76,6 @@ auth_pattern = re.compile('.*wpa_state=(.*?)\n', re.I | re.M | re.S) RALINK_DRIVER = 'ralink legacy' -def SetDNS(*args, **kargs): - """ Call the wnettools SetDNS method. """ - return wnettools.SetDNS(*args, **kargs) - -def GetDefaultGateway(*args, **kargs): - """ Call the wnettools GetDefaultGateway method. """ - return wnettools.GetDefaultGateway(*args, **kargs) - -def StopDHCP(*args, **kargs): - """ Call the wnettools StopDHCP method. """ - return wnettools.StopDHCP(*args, **kargs) - -def GetWirelessInterfaces(*args, **kargs): - """ Call the wnettools GetWirelessInterfaces method. """ - return wnettools.GetWirelessInterfaces(*args, **kargs) - -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 @@ -220,10 +194,10 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): except (IOError, ValueError, TypeError): print 'Error checking link using /sys/class/net/%s/carrier' % self.iface - if self.ETHTOOL_FOUND and self.link_detect != misc.MIITOOL: - return self._eth_get_plugged_in() - elif self.MIITOOL_FOUND: + if self.miitool_cmd and self.link_detect == misc.MIITOOL: return self._mii_get_plugged_in() + elif self.ethtool_cmd: + return self._eth_get_plugged_in() else: print 'Error: No way of checking for a wired connection. Make ' + \ 'sure that either mii-tool or ethtool is installed.' @@ -236,14 +210,15 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): True if a link is detected, False otherwise. """ - link_tool = 'ethtool' + cmd = "%s %s" % (self.ethtool_cmd, self.iface) if not self.IsUp(): print 'Wired Interface is down, putting it up' self.Up() time.sleep(6) - tool_data = misc.Run(link_tool + ' ' + self.iface, True) - if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M | - re.S), tool_data) is not None: + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) + if misc.RunRegex(re.compile('(Link detected: yes)', re.I | re.M | re.S), + tool_data): return True else: return False @@ -255,14 +230,16 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): True if a link is detected, False otherwise. """ - link_tool = 'mii-tool' - tool_data = misc.Run(link_tool + ' ' + self.iface, True) + cmd = "%s %s" % (self.miitool_cmd, self.iface) + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) if misc.RunRegex(re.compile('(Invalid argument)', re.I | re.M | re.S), tool_data) is not None: print 'Wired Interface is down, putting it up' self.Up() time.sleep(4) - tool_data = misc.Run(link_tool + ' ' + self.iface, True) + if self.verbose: print cmd + tool_data = misc.Run(cmd, include_stderr=True) if misc.RunRegex(re.compile('(link ok)', re.I | re.M | re.S), tool_data) is not None: @@ -421,14 +398,14 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): """ # Right now there's no way to do this for these drivers - if self.wpa_driver == RALINK_DRIVER or not self.WPA_CLI_FOUND: + if self.wpa_driver == RALINK_DRIVER or not self.wpa_cli_cmd: return True MAX_TIME = 35 MAX_DISCONNECTED_TIME = 3 disconnected_time = 0 while (time.time() - auth_time) < MAX_TIME: - cmd = 'wpa_cli -i ' + self.iface + ' status' + cmd = '%s -i %s status' % (self.wpa_cli_cmd, self.iface) output = misc.Run(cmd) result = misc.RunRegex(auth_pattern, output) if self.verbose: diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index eb5f807..b43f6d6 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -6,8 +6,6 @@ This module implements functions to control and obtain information from network interfaces. It utilizes ioctl calls and python modules to obtain this information whenever possible. -def SetDNS() -- Set the DNS servers of the system. -def GetWirelessInterfaces() -- Get the wireless interfaces available. class Interface() -- Control a network interface. class WiredInterface() -- Control a wired network interface. class WirelessInterface() -- Control a wireless network interface. @@ -31,9 +29,10 @@ class WirelessInterface() -- Control a wireless network interface. # along with this program. If not, see . # -import wicd.misc as misc -import wicd.wnettools as wnettools -import wicd.wpath as wpath +from wicd import misc +from wicd import wnettools +from wicd import wpath +from wicd.wnettools import * import iwscan import wpactrl @@ -82,29 +81,6 @@ SIOCGMIIPHY = 0x8947 SIOCETHTOOL = 0x8946 SIOCGIFFLAGS = 0x8913 -def SetDNS(*args, **kargs): - """ Call the wnettools SetDNS method. """ - return wnettools.SetDNS(*args, **kargs) - -def GetDefaultGateway(*args, **kargs): - """ Call the wnettools GetDefaultGateway method. """ - return wnettools.GetDefaultGateway(*args, **kargs) - -def StopDHCP(*args, **kargs): - """ Call the wnettools StopDHCP method. """ - return wnettools.StopDHCP(*args, **kargs) - -def GetWirelessInterfaces(*args, **kargs): - """ Call the wnettools GetWirelessInterfaces method. """ - return wnettools.GetWirelessInterfaces(*args, **kargs) - -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. @@ -215,9 +191,9 @@ class WiredInterface(Interface, wnettools.BaseWiredInterface): """ if not self.iface: return False - if self.ETHTOOL_FOUND and self.link_detect != misc.MIITOOL: + if self.ethtool_cmd and self.link_detect != misc.MIITOOL: return self._eth_get_plugged_in() - elif self.MIITOOL_FOUND: + elif self.miitool_cmd: return self._mii_get_plugged_in() else: print 'Error: No way of checking for a wired connection. Make \ diff --git a/wicd/gui.py b/wicd/gui.py index 162cbec..8cb6497 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -37,6 +37,7 @@ from dbus import version as dbus_version from wicd import misc from wicd import wpath from wicd import dbusmanager +from wicd import prefs from wicd.misc import noneToString from wicd.netentry import WiredNetworkEntry, WirelessNetworkEntry from wicd.prefs import PreferencesDialog @@ -45,12 +46,6 @@ from wicd.guiutil import error, GreyLabel, LabelEntry, SmallLabel if __name__ == '__main__': wpath.chdir(__file__) -try: - import pygtk - pygtk.require("2.0") -except: - pass - proxy_obj = daemon = wireless = wired = bus = None language = misc.get_language_list_gui() DBUS_AVAIL = False @@ -71,6 +66,7 @@ def setup_dbus(force=True): return False else: return False + prefs.setup_dbus() bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] diff --git a/wicd/misc.py b/wicd/misc.py index 0b0a5f2..d71b749 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -29,26 +29,40 @@ from commands import getoutput # wicd imports import wpath -if __name__ == '__main__': - wpath.chdir(__file__) - +# Connection state constants NOT_CONNECTED = 0 CONNECTING = 1 WIRELESS = 2 WIRED = 3 SUSPENDED = 4 +# Automatic app selection constant AUTO = 0 + +# DHCP Clients DHCLIENT = 1 DHCPCD = 2 PUMP = 3 +# Link detection tools ETHTOOL = 1 MIITOOL = 2 +# Route flushing tools IP = 1 ROUTE = 2 +# Graphical sudo apps +GKSUDO = 1 +KDESU = 2 +KTSUSS = 3 +sudo_dict = { + AUTO : "", + GKSUDO : "gksudo", + KDESU : "kdesu", + KTSUSS: "ktsuss", +} + class WicdError(Exception): pass @@ -375,9 +389,9 @@ def detect_desktop_environment(): pass return desktop_environment -def get_sudo_cmd(msg): +def get_sudo_cmd(msg, prog_num=0): """ Returns a graphical sudo command for generic use. """ - sudo_prog = choose_sudo_prog() + sudo_prog = choose_sudo_prog(prog_num) if not sudo_prog: return None if re.search("(ktsuss|gksu|gksudo)$", sudo_prog): msg_flag = "-m" @@ -385,8 +399,10 @@ def get_sudo_cmd(msg): msg_flag = "--caption" return [sudo_prog, msg_flag, msg] -def choose_sudo_prog(): +def choose_sudo_prog(prog_num=0): """ Try to intelligently decide which graphical sudo program to use. """ + if prog_num: + return find_path(sudo_dict[prog_num]) desktop_env = detect_desktop_environment() env_path = os.environ['PATH'].split(":") @@ -412,7 +428,10 @@ 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").split(':') + if not paths: + paths = ["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", + "/sbin", "/bin"] for path in paths: if os.path.exists(os.path.join(path, cmd)): return os.path.join(path, cmd) diff --git a/wicd/monitor.py b/wicd/monitor.py index ef7f104..2e4bac7 100755 --- a/wicd/monitor.py +++ b/wicd/monitor.py @@ -275,8 +275,9 @@ class ConnectionStatus(object): return # Some checks to keep reconnect retries from going crazy. - if self.reconnect_tries > 2 and \ - (time.time() - self.last_reconnect_time) < 300: + if (self.reconnect_tries > 3 and + (time.time() - self.last_reconnect_time) < 200): + print "Throttling autoreconnect" return self.reconnecting = True diff --git a/wicd/netentry.py b/wicd/netentry.py index 0616e5b..8b4f541 100644 --- a/wicd/netentry.py +++ b/wicd/netentry.py @@ -237,7 +237,8 @@ class WiredSettingsDialog(AdvancedSettingsDialog): profile = self.prof_name cmdend = [os.path.join(wpath.lib, "configscript.py"), profile, "wired"] if os.getuid() != 0: - cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) + cmdbase = misc.get_sudo_cmd(language['scripts_need_pass'], + prog_num=daemon.GetSudoApp()) if not cmdbase: error(None, language["no_sudo_prog"]) return @@ -336,7 +337,8 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): cmdend = [os.path.join(wpath.lib, "configscript.py"), str(self.networkID), "wireless"] if os.getuid() != 0: - cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) + cmdbase = misc.get_sudo_cmd(language['scripts_need_pass'], + prog_num=daemon.GetSudoApp()) if not cmdbase: error(None, language["no_sudo_prog"]) return diff --git a/wicd/networking.py b/wicd/networking.py index 6e3e8c2..02a659f 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -105,10 +105,34 @@ def get_backend_description_dict(): if be: d[be] = get_backend_description(be) return d + +def expand_script_macros(script, msg, bssid, essid): + """Expands any supported macros in a script. + + Keyword arguments: + script -- the script to execute. + msg -- the name of the script, %{script} will be expanded to this. + bssid -- the bssid of the network we connect to, defaults to 'wired'. + essid -- the essid of the network we connect to, defaults to 'wired'.""" + def repl(match): + macro = match.group(1).lower() + if macro_dict.has_key(macro): + return macro_dict[macro] + print 'Warning: found illegal macro %s in %s script' % (macro, msg) + return match.group() + + macro_dict = { 'script' : msg, + 'bssid' : bssid, + 'essid' : essid } + regex = re.compile(r'%\{([a-zA-Z0-9]+)\}') + expanded = regex.sub(repl, script) + print "Expanded '%s' to '%s'" % (script, expanded) + return expanded + class Controller(object): """ Parent class for the different interface types. """ - def __init__(self): + def __init__(self, debug=False): """ Initialise the class. """ self.global_dns_1 = None self.global_dns_2 = None @@ -117,7 +141,7 @@ class Controller(object): self.global_search_dom = None self._dhcp_client = None self._flush_tool = None - self._debug = None + self._debug = debug self._backend = None self.connecting_thread = None self.before_script = None @@ -138,8 +162,6 @@ class Controller(object): self._dhcp_client = value if self.iface: self.iface.DHCP_CLIENT = value - self.iface.CheckDHCP() - def get_dhcp_client(self): return self._dhcp_client dhcp_client = property(get_dhcp_client, set_dhcp_client) @@ -166,6 +188,7 @@ class Controller(object): return True def StopDHCP(self): + """ Stops all running DHCP clients. """ return BACKEND.StopDHCP() def GetIP(self, ifconfig=""): @@ -214,32 +237,11 @@ class Controller(object): """ return self.iface.Down() - -def expand_script_macros(script, msg, bssid, essid): - """Expands any supported macros in a script. - - Keyword arguments: - script -- the script to execute. - msg -- the name of the script, %{script} will be expanded to this. - bssid -- the bssid of the network we connect to, defaults to 'wired'. - essid -- the essid of the network we connect to, defaults to 'wired'.""" - - macro_dict = { 'script' : msg, - 'bssid' : bssid, - 'essid' : essid } - # Define a replacement function, this is done here so that %{script} will be substituted correctly - def repl(match): - macro = match.group( 1 ).lower() - if macro_dict.has_key( macro ): - return macro_dict[macro] - print 'Warning: found illegal macro %s in %s script' % (macro, msg) - return match.group() - - regex = re.compile( r'%\{([a-zA-Z0-9]+)\}' ) - expanded = regex.sub( repl, script ) - print "Expanded '%s' to '%s'" % (script, expanded) - return expanded + def AppAvailable(self, app): + """ Determine if the given application is installed. """ + return self.iface.AppAvailable(app) + class ConnectThread(threading.Thread): """ A class to perform network connections in a multi-threaded way. @@ -475,9 +477,9 @@ class ConnectThread(threading.Thread): class Wireless(Controller): """ A wrapper for common wireless interface functions. """ - def __init__(self): + def __init__(self, debug=False): """ Initialize the class. """ - Controller.__init__(self) + Controller.__init__(self, debug=debug) self._wpa_driver = None self._wireless_interface = None self.wiface = None @@ -666,7 +668,11 @@ class Wireless(Controller): The first available wireless interface. """ - return BACKEND.GetWirelessInterfaces() + ifaces = BACKEND.GetWirelessInterfaces() + if ifaces: + return ifaces[0] + else: + return None def GetKillSwitchStatus(self): """ Get the current status of the Killswitch. @@ -838,9 +844,9 @@ class WirelessConnectThread(ConnectThread): class Wired(Controller): """ A wrapper for common wired interface functions. """ - def __init__(self): + def __init__(self, debug=False): """ Initialise the class. """ - Controller.__init__(self) + Controller.__init__(self, debug=debug) self.wpa_driver = None self._link_detect = None self._wired_interface = None diff --git a/wicd/prefs.py b/wicd/prefs.py index a674ea1..8ec7ae1 100644 --- a/wicd/prefs.py +++ b/wicd/prefs.py @@ -32,6 +32,7 @@ import gtk.glade from wicd import misc from wicd import wpath +from wicd import dbusmanager from wicd.misc import checkboxTextboxToggle, noneToBlankString daemon = None @@ -40,17 +41,37 @@ wired = None language = misc.get_language_list_gui() +def setup_dbus(): + global daemon, wireless, wired + daemon = dbusmanager.get_interface('daemon') + wireless = dbusmanager.get_interface('wireless') + wired = dbusmanager.get_interface('wired') + class PreferencesDialog(object): """ Class for handling the wicd preferences dialog window. """ def __init__(self, wTree, dbus): - global daemon, wireless, wired - daemon = dbus['daemon'] - wireless = dbus['wireless'] - wired = dbus['wired'] + setup_dbus() self.wTree = wTree self.prep_settings_diag() self.load_preferences_diag() + def _setup_external_app_radios(self, radio_list, get_method, set_method): + """ Generic function for setting up external app radios. """ + def set_available(apps): + for app in apps: + app.set_sensitive(daemon.GetAppAvailable(app.get_label())) + + # Disable radios for apps that aren't installed. + set_available(radio_list[1:]) + selected_app = get_method() + # Make sure the app we want to select is actually available. + if radio_list[selected_app].get_property("sensitive"): + radio_list[selected_app].set_active(True) + else: + # If it isn't, default to Automatic. + set_method(misc.AUTO) + radio_list[misc.AUTO].set_active(True) + def load_preferences_diag(self): """ Loads data into the preferences Dialog. """ @@ -62,19 +83,24 @@ class PreferencesDialog(object): dhcp_list = [self.dhcpautoradio, self.dhclientradio, self.dhcpcdradio, self.pumpradio] - dhcp_method = daemon.GetDHCPClient() - print 'DHCP method is %s' % daemon.GetDHCPClient() - dhcp_list[dhcp_method].set_active(True) + self._setup_external_app_radios(dhcp_list, daemon.GetDHCPClient, + daemon.SetDHCPClient) wired_link_list = [self.linkautoradio, self.ethtoolradio, self.miitoolradio] - wired_link_method = daemon.GetLinkDetectionTool() - wired_link_list[wired_link_method].set_active(True) + self._setup_external_app_radios(wired_link_list, + daemon.GetLinkDetectionTool, + daemon.SetLinkDetectionTool) flush_list = [self.flushautoradio, self.ipflushradio, self.routeflushradio] - flush_method = daemon.GetFlushTool() - flush_list[flush_method].set_active(True) + self._setup_external_app_radios(flush_list, daemon.GetFlushTool, + daemon.SetFlushTool) + + sudo_list = [self.sudoautoradio, self.gksudoradio, self.kdesuradio, + self.ktsussradio] + self._setup_external_app_radios(sudo_list, daemon.GetSudoApp, + daemon.SetAudoApp) auto_conn_meth = daemon.GetWiredAutoConnectMethod() if auto_conn_meth == 1: @@ -185,6 +211,16 @@ class PreferencesDialog(object): else: flush_tool = misc.ROUTE daemon.SetFlushTool(flush_tool) + + if self.sudoautoradio.get_active(): + sudo_tool = misc.AUTO + elif self.gksudoradio.get_active(): + sudo_tool = misc.GKSUDO + elif self.kdesuradio.get_active(): + sudo_tool = misc.KDESU + else: + sudo_tool = misc.KTSUSS + daemon.SetSudoApp(sudo_tool) [width, height] = self.dialog.get_size() daemon.WriteWindowSize(width, height, "pref") @@ -289,6 +325,12 @@ class PreferencesDialog(object): 'wicd_auto_config') self.ipflushradio = setup_label("ip_flush_radio") self.routeflushradio = setup_label("route_flush_radio") + + # Graphical Sudo Apps + self.sudoautoradio = setup_label("sudo_auto_radio", "wicd_auto_config") + self.gksudoradio = setup_label("gksudo_radio") + self.kdesuradio = setup_label("kdesu_radio") + self.ktsussradio = setup_label("ktsuss_radio") # Replacement for the combo box hack self.wpadrivercombo = build_combobox("pref_wpa_combobox") @@ -317,11 +359,10 @@ class PreferencesDialog(object): # Load backend combobox self.backends = daemon.GetBackendList() self.be_descriptions = daemon.GetBackendDescriptionDict() - # "" is included as a hack for DBus limitations, so we remove it. - self.backends.remove("") for x in self.backends: - self.backendcombo.append_text(x) + if x: + self.backendcombo.append_text(x) def be_combo_changed(self, combo): """ Update the description label for the given backend. """ diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index acf8683..876c33f 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -79,10 +79,11 @@ class WicdDaemon(dbus.service.Object): """ Initializes the daemon DBus object. """ dbus.service.Object.__init__(self, bus_name=bus_name, object_path=object_path) - self.wifi = networking.Wireless() - self.wired = networking.Wired() self.config = ConfigManager(os.path.join(wpath.etc, "manager-settings.conf")) + self._debug_mode = bool(self.config.get("Settings", "debug_mode")) + self.wifi = networking.Wireless(debug=self._debug_mode) + self.wired = networking.Wired(debug=self._debug_mode) self.wired_bus= WiredDaemon(bus_name, self, wired=self.wired) self.wireless_bus = WirelessDaemon(bus_name, self, wifi=self.wifi) self.forced_disconnect = False @@ -99,6 +100,7 @@ class WicdDaemon(dbus.service.Object): self.dhcp_client = 0 self.link_detect_tool = 0 self.flush_tool = 0 + self.sudo_app = 0 # This will speed up the scanning process - if a client doesn't # need a fresh scan, just feed them the old one. A fresh scan @@ -273,8 +275,8 @@ class WicdDaemon(dbus.service.Object): """ Sets if debugging mode is on or off. """ self.config.set("Settings", "debug_mode", debug, write=True) self.debug_mode = misc.to_bool(debug) - self.wifi.debug = self.debug_mode - self.wired.debug = self.debug_mode + self.wifi.debug = debug + self.wired.debug = debug self.wireless_bus.debug_mode = debug self.wired_bus.debug_mode = debug @@ -569,6 +571,11 @@ class WicdDaemon(dbus.service.Object): """ return bool(self.need_profile_chooser) + + @dbus.service.method("org.wicd.daemon") + def GetAppAvailable(self, app): + """ Determine if a given application is available.""" + return bool(self.wifi.AppAvailable(app) or self.wired.AppAvailable(app)) @dbus.service.method('org.wicd.daemon') def GetDHCPClient(self): @@ -630,6 +637,17 @@ class WicdDaemon(dbus.service.Object): self.wired.flush_tool = int(flush_tool) self.wifi.flush_tool = int(flush_tool) self.config.set("Settings", "flush_tool", flush_tool, write=True) + + @dbus.service.method('org.wicd.daemon') + def GetSudoApp(self): + """ Get the preferred sudo app. """ + return self.sudo_app + + @dbus.service.method('org.wicd.daemon') + def SetSudoApp(self, sudo_app): + """ Set the preferred sudo app. """ + self.sudo_app = sudo_app + self.config.set("Settings", "sudo_app", sudo_app, write=True) @dbus.service.method('org.wicd.daemon') def WriteWindowSize(self, width, height, win_name): @@ -814,7 +832,6 @@ class WicdDaemon(dbus.service.Object): b_wired = self.wired_bus b_wifi = self.wireless_bus app_conf= self.config - verbose = True # Load the backend. be_def = 'external' self.SetBackend(app_conf.get("Settings", "backend", default=be_def)) @@ -845,15 +862,16 @@ class WicdDaemon(dbus.service.Object): default=True)) self.SetDebugMode(app_conf.get("Settings", "debug_mode", default=False)) self.SetWiredAutoConnectMethod(app_conf.get("Settings", - "wired_connect_mode", - default=1)) + "wired_connect_mode", + default=1)) self.SetSignalDisplayType(app_conf.get("Settings", - "signal_display_type", - default=0)) + "signal_display_type", + default=0)) self.SetDHCPClient(app_conf.get("Settings", "dhcp_client", default=0)) self.SetLinkDetectionTool(app_conf.get("Settings", "link_detect_tool", default=0)) self.SetFlushTool(app_conf.get("Settings", "flush_tool", default=0)) + self.SetSudoApp(app_conf.get("Settings", "sudo_app", default=0)) self.SetPreferWiredNetwork(app_conf.get("Settings", "prefer_wired", default=False)) app_conf.write() diff --git a/wicd/wnettools.py b/wicd/wnettools.py index ac52d31..b4bb5f6 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -38,6 +38,7 @@ from string import maketrans, translate import wpath import misc +from misc import find_path RALINK_DRIVER = 'ralink legacy' @@ -46,6 +47,9 @@ blacklist_strict = '!"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ ' blacklist_norm = ";`$!*|><&\\" blank_trans = maketrans("", "") +__all__ = ["SetDNS", "GetDefaultGateway", "GetWiredInterfaces", "StopDHCP", + "GetWirelessInterfaces", "IsValidWpaSuppDriver", "NeedsExternalCalls"] + def _sanitize_string(string): if string: return translate(str(string), blank_trans, blacklist_norm) @@ -123,7 +127,7 @@ def GetWirelessInterfaces(): ifnames = [iface for iface in os.listdir(dev_dir) if os.path.isdir(dev_dir + iface) and 'wireless' in os.listdir(dev_dir + iface)] - return bool(ifnames) and ifnames[0] or None + return ifnames def GetWiredInterfaces(): """ Returns a list of wired interfaces on the system. """ @@ -160,11 +164,6 @@ class BaseInterface(object): self.iface = _sanitize_string_strict(iface) self.verbose = verbose self.DHCP_CLIENT = None - self.DHCP_CMD = None - self.DHCP_RELEASE = None - self.MIITOOL_FOUND = False - self.ETHTOOL_FOUND = False - self.IP_FOUND = False self.flush_tool = None self.link_detect = None @@ -181,29 +180,94 @@ class BaseInterface(object): """ self.iface = _sanitize_string_strict(str(iface)) - def _find_client_path(self, client): + def _find_program_path(self, program): """ Determines the full path for the given program. - Searches a hardcoded list of paths for a given program name. + Searches for a given program name on the PATH. Keyword arguments: - client -- The name of the program to search for + program -- The name of the program to search for Returns: The full path of the program or None """ - paths = ['/sbin/', '/usr/sbin/', '/bin/', '/usr/bin/', - '/usr/local/sbin/', '/usr/local/bin/'] - for path in paths: - if os.path.exists("%s%s" % (path, client)): - return "%s%s" % (path, client) - if self.verbose: - print "WARNING: No path found for %s" % (client) - return None + path = find_path(program) + if not path and self.verbose: + print "WARNING: No path found for %s" % program + return path + + def _get_dhcp_command(self, flavor=None): + """ Returns the correct DHCP client command. + + Given a type of DHCP request (create or release a lease), + this method will build a command to complete the request + using the correct dhcp client, and cli options. + + """ + def get_client_name(cl): + """ Converts the integer value for a dhcp client to a string. """ + if (cl in [misc.DHCLIENT, "dhclient"] or + (cl == misc.AUTO and self.dhclient_cmd)): + client = "dhclient" + cmd = self.dhclient_cmd + elif (cl in [misc.DHCPCD, "dhcpcd"] or + (cl == misc.AUTO and self.dhcpcd_cmd)): + client = "dhcpcd" + cmd = self.dhcpcd_cmd + elif (cl in [misc.PUMP, "pump"] or + (cl == misc.AUTO and self.pump_cmd)): + client = "pump" + cmd = self.pump_cmd + else: + client = None + cmd = "" + return (client, cmd) + + connect_dict = { + "dhclient" : r"%s %s", + "pump" : r"%s -i %s", + "dhcpcd" : r"%s %s", + } + release_dict = { + "dhclient" : r"%s -r %s", + "pump" : r"%s -r -i %s", + "dhcpcd" : r"%s -k %s", + } + (client_name, cmd) = get_client_name(self.DHCP_CLIENT) + if not client_name or not cmd: + print "WARNING: Failed to find a valid dhcp client!" + return "" + + if flavor == "connect": + return connect_dict[client_name] % (cmd, self.iface) + elif flavor == "release": + return release_dict[client_name] % (cmd, self.iface) + else: + return str(cmd) + + def AppAvailable(self, app): + """ Return whether a given app is available. + + Given the name of an executable, determines if it is + available for use by checking for a defined 'app'_cmd + instance variable. + + """ + return bool(self.__dict__.get("%s_cmd" % app.replace("-", ""))) + + def Check(self): + """ Check that all required tools are available. """ + # THINGS TO CHECK FOR: ethtool, pptp-linux, dhclient, host + self.CheckDHCP() + self.CheckWiredTools() + self.CheckWirelessTools() + self.CheckSudoApplications() + self.CheckRouteFlushTool() + def CheckDHCP(self): - """ Check for a valid DHCP client. + """ Check for the existence of valid DHCP clients. Checks for the existence of a supported DHCP client. If one is found, the appropriate values for DHCP_CMD, DHCP_RELEASE, and @@ -211,97 +275,30 @@ class BaseInterface(object): warning is printed. """ - def get_client_name(cl): - """ Converts the integer value for a dhcp client to a string. """ - if cl in [misc.DHCLIENT, "dhclient"]: - client = "dhclient" - elif cl in [misc.DHCPCD, "dhcpcd"]: - client = "dhcpcd" - else: - client = "pump" - return client + self.dhclient_cmd = self._find_program_path("dhclient") + self.dhcpcd_cmd = self._find_program_path("dhcpcd") + self.pump_cmd = self._find_program_path("pump") - if self.DHCP_CLIENT: - dhcp_client = get_client_name(self.DHCP_CLIENT) - dhcp_path = self._find_client_path(dhcp_client) - if not dhcp_path: - print "WARNING: Could not find selected dhcp client. Wicd " + \ - " will try to find another supported client." - if not self.DHCP_CLIENT or not dhcp_path: - dhcp_client = None - dhcp_path = None - dhcpclients = ["dhclient", "dhcpcd", "pump"] - for client in dhcpclients: - dhcp_path = self._find_client_path(client) - if dhcp_path: - dhcp_client = client - break - - if not dhcp_client: - print "WARNING: No supported DHCP Client could be found!" - return - elif dhcp_client in [misc.DHCLIENT, "dhclient"]: - dhcp_client = misc.DHCLIENT - dhcp_cmd = dhcp_path - dhcp_release = dhcp_cmd + " -r" - elif dhcp_client in [misc.PUMP, "pump"]: - dhcp_client = misc.PUMP - dhcp_cmd = dhcp_path + " -i" - dhcp_release = dhcp_cmd + " -r -i" - elif dhcp_client in [misc.DHCPCD, "dhcpcd"]: - dhcp_client = misc.DHCPCD - dhcp_cmd = dhcp_path - dhcp_release = dhcp_cmd + " -k" - else: - dhcp_client = None - dhcp_cmd = None - dhcp_release = None - - self.DHCP_CMD = dhcp_cmd - self.DHCP_RELEASE = dhcp_release - self.DHCP_CLIENT = dhcp_client - def CheckWiredTools(self): """ Check for the existence of ethtool and mii-tool. """ - miitool_path = self._find_client_path("mii-tool") - if miitool_path: - self.miitool_cmd = miitool_path - self.MIITOOL_FOUND = True - else: - self.miitool_cmd = None - self.MIITOOL_FOUND = False - - ethtool_path = self._find_client_path("ethtool") - if ethtool_path: - self.ethtool_cmd = ethtool_path - self.ETHTOOL_FOUND = True - else: - self.ethtool_cmd = None - self.ETHTOOL_FOUND = False + self.miitool_cmd = self._find_program_path("mii-tool") + self.ethtool_cmd = self._find_program_path("ethtool") def CheckWirelessTools(self): """ Check for the existence of wpa_cli """ - wpa_cli_path = self._find_client_path("wpa_cli") - if wpa_cli_path: - self.WPA_CLI_FOUND = True - else: - self.WPA_CLI_FOUND = False + self.wpa_cli_cmd = self._find_program_path("wpa_cli") + if not self.wpa_cli_cmd: print "wpa_cli not found. Authentication will not be validated." - - def Check(self): - """ Check that all required tools are available. """ - # THINGS TO CHECK FOR: ethtool, pptp-linux, dhclient, host - self.CheckDHCP() - self.CheckWiredTools() - self.CheckWirelessTools() - - ip_path = self._find_client_path("ip") - if ip_path: - self.ip_cmd = ip_path - self.IP_FOUND = True - else: - self.ip_cmd = None - self.IP_FOUND = False + + def CheckRouteFlushTool(self): + """ Check for a route flush tool. """ + self.ip_cmd = self._find_program_path("ip") + self.route_cmd = self._find_program_path("route") + + def CheckSudoApplications(self): + self.gksudo_cmd = self._find_program_path("gksudo") + self.kdesu_cmd = self._find_program_path("kdesu") + self.ktsuss_cmd = self._find_program_path("ktsuss") def Up(self): """ Bring the network interface up. @@ -461,7 +458,8 @@ class BaseInterface(object): """ if not self.iface: return False - cmd = self.DHCP_CMD + " " + self.iface + cmd = "%s %s" % (self._get_dhcp_command('connect'), self.iface) + #cmd = self.DHCP_CMD + " " + self.iface if self.verbose: print cmd pipe = misc.Run(cmd, include_stderr=True, return_pipe=True) @@ -476,19 +474,23 @@ class BaseInterface(object): def ReleaseDHCP(self): """ Release the DHCP lease for this interface. """ if not self.iface: return False - cmd = self.DHCP_RELEASE + " " + self.iface + cmd = "%s %s" % (self._get_dhcp_command("release"), self.iface) + #cmd = self.DHCP_RELEASE + " " + self.iface if self.verbose: print cmd misc.Run(cmd) def FlushRoutes(self): """ Flush all network routes. """ if not self.iface: return False - if self.IP_FOUND and self.flush_tool == misc.IP: - #cmd = "ip route flush dev " + self.iface - cmds = ['ip route flush all'] - else: - cmds = ['route del default'] + if self.route_cmd and self.flush_tool == misc.ROUTE: + cmds = ['%s del default' % self.route_cmd] cmds.append('route del dev %s' % self.iface) + elif self.ip_cmd: + #cmd = "ip route flush dev " + self.iface + cmds = ['%s route flush all' % self.ip_cmd] + else: + print "No flush command available!" + cmds = [] for cmd in cmds: if self.verbose: print cmd misc.Run(cmd)