~ubuntu-branches/ubuntu/saucy/wicd/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/04-fix_resolv.conf_backup-restore.patch/wicd/wicd-daemon.py

  • Committer: Package Import Robot
  • Author(s): David Paleino
  • Date: 2012-11-02 21:49:32 UTC
  • Revision ID: package-import@ubuntu.com-20121102214932-oiqjicfuxycdwd53
Tags: 1.7.2.4-3
* Fix debian/watch
* Recommend rfkill in wicd-daemon (Closes: #683559)
* Substitute dependency on dhcp3-client with isc-dhcp-client
  (Closes: #680976)
* Fix handling of /etc/resolv.conf when it's a symlink (Closes: #691973)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
""" wicd - wireless connection daemon implementation.
 
5
 
 
6
This module implements the wicd daemon that provides network
 
7
connection management, for both wireless and wired networks. The daemon
 
8
must be run as root to control the networks, however the user interface
 
9
components should be run as a normal user.
 
10
 
 
11
class WicdDaemon() -- DBus interface to manage general wicd processes.
 
12
class WiredDaemon() -- DBus interface to managed the wired network.
 
13
class WirelessDaemon() -- DBus interface to managed the wireless network.
 
14
 
 
15
"""
 
16
 
 
17
#
 
18
#   Copyright (C) 2007 - 2009 Adam Blackburn
 
19
#   Copyright (C) 2007 - 2009 Dan O'Reilly
 
20
#   Copyright (C) 2007 - 2009 Byron Hillis
 
21
#   Copyright (C)        2009 Andrew Psaltis
 
22
#
 
23
#   This program is free software; you can redistribute it and/or modify
 
24
#   it under the terms of the GNU General Public License Version 2 as
 
25
#   published by the Free Software Foundation.
 
26
#
 
27
#   This program is distributed in the hope that it will be useful,
 
28
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
30
#   GNU General Public License for more details.
 
31
#
 
32
#   You should have received a copy of the GNU General Public License
 
33
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
34
#
 
35
 
 
36
import os
 
37
import shutil
 
38
import sys
 
39
import time
 
40
import getopt
 
41
import signal
 
42
import atexit
 
43
from subprocess import Popen
 
44
 
 
45
# DBUS
 
46
import gobject
 
47
import dbus
 
48
import dbus.service
 
49
if getattr(dbus, 'version', (0, 0, 0)) < (0, 80, 0):
 
50
    import dbus.glib
 
51
else:
 
52
    from dbus.mainloop.glib import DBusGMainLoop
 
53
    DBusGMainLoop(set_as_default=True)
 
54
 
 
55
# wicd specific libraries
 
56
from wicd import wpath
 
57
from wicd import networking
 
58
from wicd import misc
 
59
from wicd import wnettools
 
60
from wicd.misc import noneToBlankString, _status_dict
 
61
from wicd.logfile import ManagedStdio
 
62
from wicd.configmanager import ConfigManager
 
63
 
 
64
if __name__ == '__main__':
 
65
    wpath.chdir(__file__)
 
66
 
 
67
misc.RenameProcess("wicd")
 
68
 
 
69
wireless_conf = os.path.join(wpath.etc, "wireless-settings.conf")
 
70
wired_conf = os.path.join(wpath.etc, "wired-settings.conf")
 
71
dhclient_conf = os.path.join(wpath.etc, "dhclient.conf.template")
 
72
 
 
73
class WicdDaemon(dbus.service.Object):
 
74
    """ The main wicd daemon class.
 
75
 
 
76
    This class mostly contains exported DBus methods that are not
 
77
    associated directly with either wired or wireless actions.  There
 
78
    are a few exceptions to this, due to architectural limitations.
 
79
 
 
80
    """
 
81
    def __init__(self, bus_name, object_path="/org/wicd/daemon",
 
82
                 auto_connect=True):
 
83
        """ Initializes the daemon DBus object. """
 
84
        dbus.service.Object.__init__(self, bus_name=bus_name, 
 
85
                                     object_path=object_path)
 
86
        self.config = ConfigManager(os.path.join(wpath.etc,
 
87
                                                 "manager-settings.conf"))
 
88
        self._debug_mode = bool(self.config.get("Settings", "debug_mode"))
 
89
        self.wifi = networking.Wireless(debug=self._debug_mode)
 
90
        self.wired = networking.Wired(debug=self._debug_mode)
 
91
        self.wired_bus = WiredDaemon(bus_name, self, wired=self.wired)
 
92
        self.wireless_bus = WirelessDaemon(bus_name, self, wifi=self.wifi)
 
93
        self.forced_disconnect = False
 
94
        self.need_profile_chooser = False
 
95
        self.current_interface = None
 
96
        self.vpn_session =  None
 
97
        self.gui_open = False
 
98
        self.suspended = False
 
99
        self._debug_mode = False
 
100
        self.connection_state = misc.NOT_CONNECTED
 
101
        self.connection_info = [""]
 
102
        self.auto_connecting = False
 
103
        self.prefer_wired = False
 
104
        self.show_never_connect = True
 
105
        self.dhcp_client = 0
 
106
        self.link_detect_tool = 0
 
107
        self.flush_tool = 0
 
108
        self.sudo_app = 0
 
109
 
 
110
        # This will speed up the scanning process - if a client doesn't 
 
111
        # need a fresh scan, just feed them the old one.  A fresh scan
 
112
        # can be done by calling Scan(fresh=True).
 
113
        self.LastScan = []
 
114
 
 
115
        # Load the config file
 
116
        self.ReadConfig()
 
117
 
 
118
        signal.signal(signal.SIGTERM, self.DaemonClosing)
 
119
        self.DaemonStarting()
 
120
 
 
121
        # Scan since we just got started
 
122
        if not auto_connect:
 
123
            print "--no-autoconnect detected, not autoconnecting..."
 
124
            self.SetForcedDisconnect(True)
 
125
        self.wireless_bus.Scan()
 
126
 
 
127
    def get_debug_mode(self):
 
128
        return self._debug_mode
 
129
    def set_debug_mode(self, mode):
 
130
        self._debug_mode = mode
 
131
        self.config.debug = mode
 
132
    debug_mode = property(get_debug_mode, set_debug_mode)
 
133
 
 
134
    @dbus.service.method('org.wicd.daemon')
 
135
    def Hello(self):
 
136
        """ Returns the version number. 
 
137
 
 
138
        This number is major-minor-micro. Major is only incremented if minor
 
139
        reaches > 9. Minor is incremented if changes that break core stucture
 
140
        are implemented. Micro is for everything else, and micro may be
 
141
        anything >= 0. This number is effective starting wicd v1.2.0.
 
142
 
 
143
        """
 
144
        return wpath.version
 
145
 
 
146
    @dbus.service.method('org.wicd.daemon')
 
147
    def SetWiredInterface(self, interface):
 
148
        """ Sets the wired interface for the daemon to use. """
 
149
        print "setting wired interface %s" % (str(interface))
 
150
        self.wired.wired_interface = noneToBlankString(interface)
 
151
        self.config.set("Settings", "wired_interface", interface, write=True)
 
152
 
 
153
    @dbus.service.method('org.wicd.daemon')
 
154
    def SetWirelessInterface(self, interface):
 
155
        """ Sets the wireless interface the daemon will use. """
 
156
        print "setting wireless interface %s" % (str(interface))
 
157
        self.wifi.wireless_interface = noneToBlankString(interface)
 
158
        self.config.set("Settings", "wireless_interface", interface, write=True)
 
159
 
 
160
    @dbus.service.method('org.wicd.daemon')
 
161
    def SetWPADriver(self, driver):
 
162
        """ Sets the wpa driver the wpa_supplicant will use. """
 
163
        print "setting wpa driver", str(driver)
 
164
        self.wifi.wpa_driver = driver
 
165
        self.config.set("Settings", "wpa_driver", driver, write=True)
 
166
 
 
167
    @dbus.service.method('org.wicd.daemon')
 
168
    def SetUseGlobalDNS(self, use):
 
169
        """ Sets a boolean which determines if global DNS is enabled. """
 
170
        print 'setting use global dns to', use
 
171
        use = misc.to_bool(use)
 
172
        self.config.set("Settings", "use_global_dns", use, write=True)
 
173
        self.use_global_dns = use
 
174
        self.wifi.use_global_dns = use
 
175
        self.wired.use_global_dns = use
 
176
 
 
177
    @dbus.service.method('org.wicd.daemon')
 
178
    def SetGlobalDNS(self, dns1=None, dns2=None, dns3=None,
 
179
                     dns_dom =None, search_dom=None):
 
180
        """ Sets the global dns addresses. """
 
181
        print "setting global dns"
 
182
        self.config.set("Settings", "global_dns_1", misc.noneToString(dns1))
 
183
        self.dns1 = dns1
 
184
        self.wifi.global_dns_1 = dns1
 
185
        self.wired.global_dns_1 = dns1
 
186
        self.config.set("Settings", "global_dns_2", misc.noneToString(dns2))
 
187
        self.dns2 = dns2
 
188
        self.wifi.global_dns_2 = dns2
 
189
        self.wired.global_dns_2 = dns2
 
190
        self.config.set("Settings", "global_dns_3", misc.noneToString(dns3))
 
191
        self.dns3 = dns3
 
192
        self.wifi.global_dns_3 = dns3
 
193
        self.wired.global_dns_3 = dns3
 
194
        self.config.set("Settings", "global_dns_dom", misc.noneToString(dns_dom))
 
195
        self.dns_dom = dns_dom
 
196
        self.wifi.dns_dom = dns_dom
 
197
        self.wired.dns_dom = dns_dom
 
198
        self.config.set("Settings", "global_search_dom", misc.noneToString(search_dom))
 
199
        self.search_dom = search_dom
 
200
        self.wifi.global_search_dom = search_dom
 
201
        self.wired.global_search_dom = search_dom
 
202
        print 'global dns servers are', dns1, dns2, dns3
 
203
        print 'domain is %s' % dns_dom
 
204
        print 'search domain is %s' % search_dom
 
205
        self.config.write()
 
206
 
 
207
    @dbus.service.method('org.wicd.daemon')
 
208
    def SetBackend(self, backend):
 
209
        """ Sets a new backend. """
 
210
        print "setting backend to %s" % backend
 
211
        backends = networking.BACKEND_MGR.get_available_backends()
 
212
        if backend not in backends:
 
213
            print "backend %s not available, trying to fallback to another" % backend
 
214
            try:
 
215
                backend = backends[0]
 
216
            except IndexError:
 
217
                print "ERROR: no backends available!"
 
218
                return
 
219
            else:
 
220
                print "Fell back to backend %s" % backend
 
221
        self.config.set("Settings", "backend", backend, write=True)
 
222
        if backend != self.GetCurrentBackend():
 
223
            self.suspended = True
 
224
            self.wifi.LoadBackend(backend)
 
225
            self.wired.LoadBackend(backend)
 
226
            self.SignalBackendChanged(self.GetBackendUpdateInterval())
 
227
            self.SetSuspend(False)
 
228
 
 
229
    @dbus.service.method('org.wicd.daemon')
 
230
    def GetCurrentBackend(self):
 
231
        """ Returns the currently loaded backend. """
 
232
        return networking.get_current_backend()
 
233
 
 
234
    @dbus.service.method('org.wicd.daemon')
 
235
    def GetBackendUpdateInterval(self):
 
236
        """ Returns status update interval for the loaded backend. """
 
237
        return networking.get_backend_update_interval()
 
238
 
 
239
    @dbus.service.method('org.wicd.daemon')
 
240
    def GetBackendDescription(self, backend_name):
 
241
        """ Returns the description of the given backend. """
 
242
        return networking.get_backend_description(backend_name)
 
243
 
 
244
    @dbus.service.method('org.wicd.daemon')
 
245
    def GetBackendDescriptionDict(self):
 
246
        """ Returns a dict of all backend names mapped to their description. """
 
247
        return networking.get_backend_description_dict()
 
248
 
 
249
    @dbus.service.method('org.wicd.daemon')
 
250
    def GetSavedBackend(self):
 
251
        """ Returns the backend saved to disk. """
 
252
        return self.config.get("Settings", "backend")
 
253
 
 
254
    @dbus.service.method('org.wicd.daemon')
 
255
    def GetBackendList(self):
 
256
        """ Returns a list of all backends available. """
 
257
        return networking.get_backend_list()
 
258
 
 
259
    @dbus.service.method('org.wicd.daemon')
 
260
    def GetUseGlobalDNS(self):
 
261
        """ Returns a boolean that determines if global dns is enabled. """
 
262
        return bool(self.use_global_dns)
 
263
 
 
264
    @dbus.service.method('org.wicd.daemon')
 
265
    def GetWPADriver(self):
 
266
        """ Returns the wpa driver the daemon is using. """
 
267
        return str(self.wifi.wpa_driver)
 
268
 
 
269
    @dbus.service.method('org.wicd.daemon')
 
270
    def GetWiredInterface(self):
 
271
        """ Returns the wired interface. """
 
272
        return str(self.wired.wired_interface)
 
273
 
 
274
    @dbus.service.method('org.wicd.daemon')
 
275
    def GetWirelessInterface(self):
 
276
        """ Returns the wireless interface the daemon is using. """
 
277
        return str(self.wifi.wireless_interface)
 
278
 
 
279
    @dbus.service.method('org.wicd.daemon')
 
280
    def NeedsExternalCalls(self):
 
281
        """ Returns true if the loaded backend needs external calls. """
 
282
        if self.wifi:
 
283
            return self.wifi.NeedsExternalCalls()
 
284
        elif self.wired:
 
285
            return self.wired.NeedsExternalCalls()
 
286
        else:
 
287
            return True
 
288
 
 
289
    @dbus.service.method('org.wicd.daemon')
 
290
    def SetDebugMode(self, debug):
 
291
        """ Sets if debugging mode is on or off. """
 
292
        self.config.set("Settings", "debug_mode", debug, write=True)
 
293
        self.debug_mode = misc.to_bool(debug)
 
294
        self.wifi.debug = debug
 
295
        self.wired.debug = debug
 
296
        self.wireless_bus.debug_mode = debug
 
297
        self.wired_bus.debug_mode = debug
 
298
 
 
299
    @dbus.service.method('org.wicd.daemon')
 
300
    def GetDebugMode(self):
 
301
        """ Returns whether debugging is enabled. """
 
302
        return bool(self.debug_mode)
 
303
 
 
304
    @dbus.service.method('org.wicd.daemon')
 
305
    def Disconnect(self):
 
306
        """ Disconnects all networks. """
 
307
        self.SetForcedDisconnect(True)
 
308
        self.wifi.Disconnect()
 
309
        self.wired.Disconnect()
 
310
 
 
311
    @dbus.service.method('org.wicd.daemon')
 
312
    def FormatSignalForPrinting(self, signal):
 
313
        """ Returns the suffix to display after the signal strength number. """
 
314
        if self.GetSignalDisplayType() == 1:
 
315
            return '%s dBm' % signal
 
316
        else:
 
317
            try:
 
318
                if int(signal) == 101:
 
319
                    return '??%'
 
320
                else:
 
321
                    return '%s%%' % signal
 
322
            except ValueError:
 
323
                return '%s%%' % signal
 
324
 
 
325
    @dbus.service.method('org.wicd.daemon')
 
326
    def SetSuspend(self, val):
 
327
        """ Toggles whether or not monitoring connection status is suspended """
 
328
        self.suspended = val
 
329
        if self.suspended:
 
330
            self.Disconnect()
 
331
        else:
 
332
            self.SetForcedDisconnect(False)
 
333
 
 
334
    @dbus.service.method('org.wicd.daemon')
 
335
    def GetSuspend(self):
 
336
        """ Returns True if the computer is in the suspend state. """
 
337
        return self.suspended
 
338
 
 
339
    @dbus.service.method('org.wicd.daemon')
 
340
    def AutoConnect(self, fresh):
 
341
        """ Attempts to autoconnect to a wired or wireless network.
 
342
 
 
343
        Autoconnect will first try to connect to a wired network, if that 
 
344
        fails it tries a wireless connection.
 
345
 
 
346
        """
 
347
        print "Autoconnecting..."
 
348
        if self.CheckIfConnecting():
 
349
            if self.debug_mode:
 
350
                print 'Already connecting, doing nothing.'
 
351
            return
 
352
        # We don't want to rescan/connect if the gui is open.
 
353
        if self.gui_open:
 
354
            if self.debug_mode:
 
355
                print "Skipping autoconnect because GUI is open."
 
356
            return
 
357
        if self.wired_bus.CheckPluggedIn():
 
358
            if self.debug_mode:
 
359
                print "Starting wired autoconnect..."
 
360
            self._wired_autoconnect(fresh)
 
361
        else:
 
362
            if self.debug_mode:
 
363
                print "Starting wireless autoconnect..."
 
364
            self.wireless_bus._wireless_autoconnect(fresh)
 
365
 
 
366
    @dbus.service.method('org.wicd.daemon')
 
367
    def GetAutoReconnect(self):
 
368
        """ Returns the value of self.auto_reconnect. See SetAutoReconnect. """
 
369
        return bool(self.auto_reconnect)
 
370
 
 
371
    @dbus.service.method('org.wicd.daemon')
 
372
    def SetAutoReconnect(self, value):
 
373
        """ Sets the value of self.auto_reconnect.
 
374
 
 
375
        If True, wicd will try to reconnect as soon as it detects that
 
376
        an internet connection is lost.  If False, it will do nothing,
 
377
        and wait for the user to initiate reconnection.
 
378
 
 
379
        """
 
380
        print 'setting automatically reconnect when connection drops %s' % value
 
381
        self.config.set("Settings", "auto_reconnect", misc.to_bool(value), 
 
382
                        write=True)
 
383
        self.auto_reconnect = misc.to_bool(value)
 
384
 
 
385
    @dbus.service.method('org.wicd.daemon')
 
386
    def GetGlobalDNSAddresses(self):
 
387
        """ Returns the global dns addresses. """
 
388
        return (misc.noneToString(self.dns1), misc.noneToString(self.dns2),
 
389
                misc.noneToString(self.dns3), misc.noneToString(self.dns_dom),
 
390
                misc.noneToString(self.search_dom))
 
391
 
 
392
    @dbus.service.method('org.wicd.daemon')
 
393
    def CheckIfConnecting(self):
 
394
        """ Returns if a network connection is being made. """
 
395
        if self.wired_bus.CheckIfWiredConnecting() or \
 
396
           self.wireless_bus.CheckIfWirelessConnecting():
 
397
            return True
 
398
        else:
 
399
            return False
 
400
 
 
401
    @dbus.service.method('org.wicd.daemon')
 
402
    def CancelConnect(self):
 
403
        """ Cancels the wireless connection attempt """
 
404
        print 'canceling connection attempt'
 
405
        if self.wifi.connecting_thread:
 
406
            self.wifi.connecting_thread.should_die = True
 
407
            self.wifi.ReleaseDHCP()
 
408
            # We have to actually kill dhcp if its still hanging
 
409
            # around.  It could still be trying to get a lease.
 
410
            self.wifi.KillDHCP()
 
411
            self.wifi.StopWPA()
 
412
            self.wifi.connecting_thread.connect_result = 'aborted'
 
413
        if self.wired.connecting_thread:
 
414
            self.wired.connecting_thread.should_die = True
 
415
            self.wired.ReleaseDHCP()
 
416
            self.wired.KillDHCP()
 
417
            self.wired.connecting_thread.connect_result = 'aborted'
 
418
 
 
419
    @dbus.service.method('org.wicd.daemon')
 
420
    def GetCurrentInterface(self):
 
421
        """ Returns the active interface """
 
422
        return self.current_interface
 
423
 
 
424
    @dbus.service.method('org.wicd.daemon')    
 
425
    def SetCurrentInterface(self, iface):
 
426
        """ Sets the current active interface """
 
427
        self.current_interface = str(iface)
 
428
 
 
429
    @dbus.service.method('org.wicd.daemon')
 
430
    def SetNeedWiredProfileChooser(self, val):
 
431
        """ Sets the need_wired_profile_chooser variable.
 
432
 
 
433
        If set to True, that alerts the wicd frontend to display the chooser,
 
434
        if False the frontend will do nothing.  This function is only needed
 
435
        when the frontend starts up, to determine if the chooser was requested
 
436
        before the frontend was launched.
 
437
 
 
438
        """
 
439
        self.need_profile_chooser = misc.to_bool(val)
 
440
 
 
441
    @dbus.service.method('org.wicd.daemon')
 
442
    def ShouldAutoReconnect(self):
 
443
        """ Returns True if it's the right time to try autoreconnecting. """
 
444
        if self.GetAutoReconnect() and not self.CheckIfConnecting() and \
 
445
           not self.GetForcedDisconnect() and not self.auto_connecting and \
 
446
           not self.gui_open:
 
447
            return True
 
448
        else:
 
449
            return False
 
450
 
 
451
    @dbus.service.method('org.wicd.daemon')
 
452
    def GetForcedDisconnect(self):
 
453
        """ Returns the forced_disconnect status.  See SetForcedDisconnect. """
 
454
        return bool(self.forced_disconnect)
 
455
 
 
456
    @dbus.service.method('org.wicd.daemon')
 
457
    def SetForcedDisconnect(self, value):
 
458
        """ Sets the forced_disconnect status.
 
459
 
 
460
        Set to True when a user manually disconnects or cancels a connection.
 
461
        It gets set to False as soon as the connection process is manually
 
462
        started.
 
463
 
 
464
        """
 
465
        if self.debug_mode and value: print "Forced disconnect on"
 
466
        self.forced_disconnect = bool(value)
 
467
 
 
468
    @dbus.service.method('org.wicd.daemon')
 
469
    def GetSignalDisplayType(self):
 
470
        """ Returns the signal display type.
 
471
 
 
472
        Returns either 0 or 1.
 
473
        0 for signal strength as a percentage
 
474
        1 for signal strength measured in dBm
 
475
 
 
476
        """
 
477
        return int(self.signal_display_type)
 
478
 
 
479
    @dbus.service.method('org.wicd.daemon')
 
480
    def SetSignalDisplayType(self, value):
 
481
        """ Sets the signal display type and writes it the wicd config file. """
 
482
        self.config.set("Settings", "signal_display_type", value, write=True)
 
483
        self.signal_display_type = int(value)
 
484
 
 
485
    @dbus.service.method('org.wicd.daemon')
 
486
    def GetGUIOpen(self):
 
487
        """ Returns the value of gui_open.
 
488
 
 
489
        Returns the vlaue of gui_open, which is a boolean that keeps track
 
490
        of the state of the wicd GUI.  If the GUI is open, wicd will not
 
491
        try to automatically reconnect to networks, as this behavior can
 
492
        be annoying for the user while trying to use the GUI.
 
493
 
 
494
        NOTE: It's possible for this to become out of sync, particularly if
 
495
        the wicd.py is not exited properly while the GUI is open.  We should
 
496
        probably implement some kind of pid system to do it properly.
 
497
 
 
498
        ANOTHER NOTE: This isn't used by anything yet!
 
499
 
 
500
        """
 
501
        return bool(self.gui_open)
 
502
 
 
503
    @dbus.service.method('org.wicd.daemon')
 
504
    def SetGUIOpen(self, val):
 
505
        """ Sets the value of gui_open. """
 
506
        self.gui_open = bool(val)
 
507
 
 
508
    @dbus.service.method('org.wicd.daemon')
 
509
    def SetAlwaysShowWiredInterface(self, value):
 
510
        """ Sets always_show_wired_interface to the given value. """
 
511
        self.config.set("Settings", "always_show_wired_interface", 
 
512
                        misc.to_bool(value), write=True)
 
513
        self.always_show_wired_interface = misc.to_bool(value)
 
514
 
 
515
    @dbus.service.method('org.wicd.daemon')
 
516
    def GetAlwaysShowWiredInterface(self):
 
517
        """ Returns always_show_wired_interface """
 
518
        return bool(self.always_show_wired_interface)
 
519
 
 
520
    @dbus.service.method('org.wicd.daemon')
 
521
    def SetWiredAutoConnectMethod(self, method):
 
522
        """ Sets which method to use to autoconnect to wired networks. """
 
523
        # 1 = default profile
 
524
        # 2 = show list
 
525
        # 3 = last used profile
 
526
        self.config.set("Settings", "wired_connect_mode", int(method),
 
527
                        write=True)
 
528
        self.wired_connect_mode = int(method)
 
529
        self.wired_bus.connect_mode = int(method)
 
530
        
 
531
    @dbus.service.method('org.wicd.daemon')
 
532
    def SetShouldVerifyAp(self, value):
 
533
        """ Enable/disable wireless AP verification.
 
534
        
 
535
        If this is True, wicd will try to verify that we are associated
 
536
        with the Wireless AP after a connection attempt appears to
 
537
        succeed.
 
538
        
 
539
        """
 
540
        self.config.set("Settings", "should_verify_ap", int(value), write=True)
 
541
        self.wifi.should_verify_ap = misc.to_bool(value)
 
542
        
 
543
    @dbus.service.method('org.wicd.daemon')
 
544
    def GetShouldVerifyAp(self):
 
545
        """ Returns current value for WAP connection verification. """
 
546
        return bool(self.wifi.should_verify_ap)
 
547
 
 
548
    @dbus.service.method('org.wicd.daemon')
 
549
    def GetWiredAutoConnectMethod(self):
 
550
        """ Returns the wired autoconnect method. """
 
551
        return int(self.wired_connect_mode)
 
552
 
 
553
    @dbus.service.method('org.wicd.daemon')
 
554
    def GetPreferWiredNetwork(self):
 
555
        """ Returns True if wired network preference is set. 
 
556
 
 
557
        If this is True, wicd will switch from a wireless connection
 
558
        to a wired one if an ethernet connection is available.
 
559
 
 
560
        """
 
561
        return self.prefer_wired
 
562
 
 
563
    @dbus.service.method('org.wicd.daemon')
 
564
    def SetPreferWiredNetwork(self, value):
 
565
        """ Sets the prefer_wired state. """
 
566
        self.config.set("Settings", "prefer_wired", bool(value), write=True)
 
567
        self.prefer_wired = bool(value)
 
568
 
 
569
    @dbus.service.method('org.wicd.daemon')
 
570
    def GetShowNeverConnect(self):
 
571
        """ Returns True if show_never_connect is set
 
572
 
 
573
        if True then the client will show networks marked as never connect
 
574
        """
 
575
        return self.show_never_connect
 
576
 
 
577
    @dbus.service.method('org.wicd.daemon')
 
578
    def SetShowNeverConnect(self, value):
 
579
        """ Sets the how_never_connect state. """
 
580
        self.config.set("Settings", "show_never_connect", bool(value), write=True)
 
581
        self.show_never_connect = bool(value)
 
582
 
 
583
    @dbus.service.method('org.wicd.daemon')
 
584
    def SetConnectionStatus(self, state, info):
 
585
        """ Sets the connection status.
 
586
 
 
587
        Keyword arguments:
 
588
        state - An int representing the state of the connection as defined
 
589
        in misc.py.
 
590
 
 
591
        info - a list of strings containing data about the connection state.  
 
592
        The contents of this list are dependent on the connection state.
 
593
 
 
594
        state - info contents:
 
595
        NOT_CONNECTED - info[0] = ""
 
596
        CONNECTING - info[0] = "wired" or "wireless"
 
597
                     info[1] = None if wired, an essid if wireless
 
598
        WIRED - info[0] = IP Adresss
 
599
        WIRELESS - info[0] = IP Address
 
600
                   info[1] = essid
 
601
                   info[2] = signal strength
 
602
                   info[3] = internal networkid
 
603
                   info[4] = bitrate
 
604
        SUSPENDED - info[0] = ""
 
605
 
 
606
 
 
607
        """
 
608
        self.connection_state = state
 
609
        self.connection_info = info
 
610
 
 
611
    @dbus.service.method('org.wicd.daemon', out_signature='(uas)')
 
612
    def GetConnectionStatus(self):
 
613
        """ Returns the current connection state in list form. 
 
614
 
 
615
        See SetConnectionStatus for more information about the
 
616
        data structure being returned.
 
617
 
 
618
        """
 
619
        return [self.connection_state, self.connection_info]
 
620
 
 
621
    @dbus.service.method('org.wicd.daemon')
 
622
    def GetNeedWiredProfileChooser(self):
 
623
        """ Returns need_profile_chooser.
 
624
 
 
625
        Returns a boolean specifying if the wired profile chooser needs to
 
626
        be launched.
 
627
 
 
628
        """
 
629
        return bool(self.need_profile_chooser)
 
630
 
 
631
    @dbus.service.method("org.wicd.daemon")
 
632
    def GetAppAvailable(self, app):
 
633
        """ Determine if a given  application is available."""
 
634
        return bool(self.wifi.AppAvailable(app) or self.wired.AppAvailable(app))
 
635
 
 
636
    @dbus.service.method('org.wicd.daemon')
 
637
    def GetDHCPClient(self):
 
638
        """ Returns the current DHCP client constant.
 
639
 
 
640
        See misc.py for a definition of the constants.
 
641
 
 
642
        """
 
643
        return self.dhcp_client
 
644
 
 
645
    @dbus.service.method('org.wicd.daemon')
 
646
    def SetDHCPClient(self, client):
 
647
        """ Sets the DHCP client constant.
 
648
 
 
649
        See misc.py for a definition of the constants.
 
650
 
 
651
        """
 
652
        print "Setting dhcp client to %i" % (int(client))
 
653
        self.dhcp_client = int(client)
 
654
        self.wifi.dhcp_client = int(client)
 
655
        self.wired.dhcp_client = int(client)
 
656
        self.config.set("Settings", "dhcp_client", client, write=True)
 
657
 
 
658
    @dbus.service.method('org.wicd.daemon')
 
659
    def GetLinkDetectionTool(self):
 
660
        """ Returns the current link detection tool constant. """
 
661
        return self.link_detect_tool
 
662
 
 
663
    @dbus.service.method('org.wicd.daemon')
 
664
    def SetLinkDetectionTool(self, link_tool):
 
665
        """ Sets the link detection tool. 
 
666
 
 
667
        Sets the value of the tool wicd should use to detect if a
 
668
        cable is plugged in.  If using a backend that doesn't use
 
669
        an external call to get this information (such as ioctl)
 
670
        it will instead use the ioctls provided by the specified
 
671
        tool to query for link status.
 
672
 
 
673
        """
 
674
        self.link_detect_tool = int(link_tool)
 
675
        self.wired.link_detect = int(link_tool)
 
676
        self.config.set("Settings", "link_detect_tool", link_tool, write=True)
 
677
 
 
678
    @dbus.service.method('org.wicd.daemon')
 
679
    def GetFlushTool(self):
 
680
        """ Returns the current flush tool constant. """
 
681
        return self.flush_tool
 
682
 
 
683
    @dbus.service.method('org.wicd.daemon')
 
684
    def SetFlushTool(self, flush_tool):
 
685
        """ Sets the flush tool.
 
686
 
 
687
        Sets the value of the tool wicd should use to flush routing tables.
 
688
        The value is associated with a particular tool, as specified in
 
689
        misc.py
 
690
 
 
691
        """
 
692
        self.flush_tool = int(flush_tool)
 
693
        self.wired.flush_tool = int(flush_tool)
 
694
        self.wifi.flush_tool = int(flush_tool)
 
695
        self.config.set("Settings", "flush_tool", flush_tool, write=True)
 
696
 
 
697
    @dbus.service.method('org.wicd.daemon')
 
698
    def GetSudoApp(self):
 
699
        """ Get the preferred sudo app. """
 
700
        return self.sudo_app
 
701
 
 
702
    @dbus.service.method('org.wicd.daemon')
 
703
    def SetSudoApp(self, sudo_app):
 
704
        """ Set the preferred sudo app. """
 
705
        self.sudo_app = sudo_app
 
706
        self.config.set("Settings", "sudo_app", sudo_app, write=True)
 
707
 
 
708
    def _wired_autoconnect(self, fresh=True):
 
709
        """ Attempts to autoconnect to a wired network. """
 
710
        wiredb = self.wired_bus
 
711
        if self.GetWiredAutoConnectMethod() == 3 and \
 
712
           not self.GetNeedWiredProfileChooser():
 
713
            # attempt to smartly connect to a wired network
 
714
            # by using various wireless networks detected
 
715
            # and by using plugged in USB devices
 
716
            print self.LastScan
 
717
        if self.GetWiredAutoConnectMethod() == 2 and \
 
718
           not self.GetNeedWiredProfileChooser():
 
719
            self.LaunchChooser()
 
720
            return True
 
721
 
 
722
        # Default Profile.
 
723
        elif self.GetWiredAutoConnectMethod() == 1:
 
724
            network = wiredb.GetDefaultWiredNetwork()
 
725
            if not network:
 
726
                print "Couldn't find a default wired connection," + \
 
727
                      " wired autoconnect failed."
 
728
                self.wireless_bus._wireless_autoconnect(fresh)
 
729
                return
 
730
 
 
731
        # Last-Used.
 
732
        else:
 
733
            network = wiredb.GetLastUsedWiredNetwork()
 
734
            if not network:
 
735
                print "no previous wired profile available, wired " + \
 
736
                      "autoconnect failed."
 
737
                self.wireless_bus._wireless_autoconnect(fresh)
 
738
                return
 
739
 
 
740
        wiredb.ReadWiredNetworkProfile(network)
 
741
        wiredb.ConnectWired()
 
742
        print "Attempting to autoconnect with wired interface..."
 
743
        self.auto_connecting = True
 
744
        time.sleep(1.5)
 
745
        try:
 
746
            gobject.timeout_add_seconds(3, self._monitor_wired_autoconnect, 
 
747
                                        fresh)
 
748
        except:
 
749
            gobject.timeout_add(3000, self._monitor_wired_autoconnect, fresh)
 
750
        return True
 
751
 
 
752
    def _monitor_wired_autoconnect(self, fresh):
 
753
        """ Monitor a wired auto-connection attempt.
 
754
 
 
755
        Helper method called on a timer that monitors a wired
 
756
        connection attempt and makes decisions about what to
 
757
        do next based on the result.
 
758
 
 
759
        """
 
760
        wiredb = self.wired_bus
 
761
        if wiredb.CheckIfWiredConnecting():
 
762
            return True
 
763
        elif wiredb.GetWiredIP():
 
764
            self.auto_connecting = False
 
765
            return False
 
766
        elif not self.wireless_bus.CheckIfWirelessConnecting():
 
767
            self.wireless_bus._wireless_autoconnect(fresh)
 
768
            return False
 
769
        self.auto_connecting = False
 
770
        return False
 
771
 
 
772
    @dbus.service.method("org.wicd.daemon")
 
773
    def ConnectResultsAvailable(self):
 
774
        if ((self.wired.connecting_thread and self.wired.connecting_thread.connect_result) or 
 
775
            (self.wifi.connecting_thread and self.wifi.connecting_thread.connect_result)):
 
776
            return True
 
777
        else:
 
778
            return False
 
779
 
 
780
    @dbus.service.method("org.wicd.daemon")
 
781
    def SendConnectResultsIfAvail(self):
 
782
        if self.ConnectResultsAvailable():
 
783
            self.SendConnectResult()
 
784
 
 
785
    @dbus.service.method("org.wicd.daemon")
 
786
    def SendConnectResult(self):
 
787
        if self.wired.connecting_thread and self.wired.connecting_thread.connect_result:
 
788
            self.ConnectResultsSent(self.wired.connecting_thread.connect_result)
 
789
            self.wired.connecting_thread.connect_result = ""
 
790
        elif self.wifi.connecting_thread and self.wifi.connecting_thread.connect_result:
 
791
            self.ConnectResultsSent(self.wifi.connecting_thread.connect_result)
 
792
            self.wifi.connecting_thread.connect_result = ""
 
793
 
 
794
    @dbus.service.signal(dbus_interface="org.wicd.daemon",signature='s')
 
795
    def ConnectResultsSent(self, result):
 
796
        print "Sending connection attempt result %s" % result
 
797
 
 
798
    @dbus.service.method("org.wicd.daemon")
 
799
    @dbus.service.signal(dbus_interface="org.wicd.daemon", signature='')
 
800
    def UpdateState(self):
 
801
        pass
 
802
 
 
803
    @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='')
 
804
    def LaunchChooser(self):
 
805
        """ Emits the wired profile chooser dbus signal. """
 
806
        print 'calling wired profile chooser'
 
807
        self.SetNeedWiredProfileChooser(True)
 
808
 
 
809
    @dbus.service.signal(dbus_interface="org.wicd.daemon", signature='')
 
810
    def DaemonStarting(self):
 
811
        """ Emits a signa indicating the daemon is starting. """
 
812
        pass
 
813
 
 
814
    @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='')
 
815
    def DaemonClosing(self):
 
816
        """ Emits a signal indicating the daemon will be closing. """
 
817
        pass
 
818
 
 
819
    @dbus.service.method('org.wicd.daemon', in_signature='uav')
 
820
    def EmitStatusChanged(self, state, info):
 
821
        """ Calls the StatusChanged signal method. """
 
822
        self.StatusChanged(state, info)
 
823
 
 
824
    @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='uav')
 
825
    def StatusChanged(self, state, info):
 
826
        """ Emits a "status changed" dbus signal.
 
827
 
 
828
        This D-Bus signal is emitted when the connection status changes.
 
829
        This signal can be hooked to monitor the network state.
 
830
 
 
831
        """
 
832
        pass
 
833
    
 
834
    @dbus.service.signal(dbus_interface='org.wicd.daemon', signature='i')
 
835
    def SignalBackendChanged(self, interval):
 
836
        """ Emits a signal when the current backend changes. """
 
837
        pass
 
838
 
 
839
    def ReadConfig(self):
 
840
        """ Reads the manager-settings.conf file.
 
841
 
 
842
        Reads the manager-settings.conf file and loads the stored
 
843
        values into memory.
 
844
 
 
845
        """
 
846
        b_wired = self.wired_bus
 
847
        b_wifi = self.wireless_bus
 
848
        app_conf = self.config
 
849
        # Load the backend.
 
850
        be_def = 'external'
 
851
        self.SetBackend(app_conf.get("Settings", "backend", default=be_def))
 
852
 
 
853
        # Load network interfaces.
 
854
        iface = self.wireless_bus.DetectWirelessInterface()
 
855
        if not iface: iface = 'wlan0'
 
856
        self.SetWirelessInterface(app_conf.get("Settings", "wireless_interface",
 
857
                                               default=iface))
 
858
        iface = self.wired_bus.DetectWiredInterface()
 
859
        if not iface: iface = 'eth0'
 
860
        self.SetWiredInterface(app_conf.get("Settings", "wired_interface",
 
861
                                            default=iface))
 
862
 
 
863
        self.SetWPADriver(app_conf.get("Settings", "wpa_driver", default="wext"))
 
864
        self.SetAlwaysShowWiredInterface(app_conf.get("Settings",
 
865
                                                      "always_show_wired_interface",
 
866
                                                      default=False))
 
867
        self.SetUseGlobalDNS(app_conf.get("Settings", "use_global_dns",
 
868
                                          default=False))
 
869
        dns1 = app_conf.get("Settings", "global_dns_1", default='None')
 
870
        dns2 = app_conf.get("Settings", "global_dns_2", default='None')
 
871
        dns3 = app_conf.get("Settings", "global_dns_3", default='None')
 
872
        dns_dom = app_conf.get("Settings", "global_dns_dom", default='None')
 
873
        search_dom = app_conf.get("Settings", "global_search_dom", default='None')
 
874
        self.SetGlobalDNS(dns1, dns2, dns3, dns_dom, search_dom)
 
875
        self.SetAutoReconnect(app_conf.get("Settings", "auto_reconnect",
 
876
                                           default=True))
 
877
        self.SetDebugMode(app_conf.get("Settings", "debug_mode", default=False))
 
878
        self.SetWiredAutoConnectMethod(app_conf.get("Settings",
 
879
                                                    "wired_connect_mode",
 
880
                                                    default=1))
 
881
        self.SetSignalDisplayType(app_conf.get("Settings", 
 
882
                                               "signal_display_type",
 
883
                                               default=0))
 
884
        self.SetShouldVerifyAp(app_conf.get("Settings", "should_verify_ap",
 
885
                                            default=1))
 
886
        self.SetDHCPClient(app_conf.get("Settings", "dhcp_client", default=0))
 
887
        self.SetLinkDetectionTool(app_conf.get("Settings", "link_detect_tool",
 
888
                                               default=0))
 
889
        self.SetFlushTool(app_conf.get("Settings", "flush_tool", default=0))
 
890
        self.SetSudoApp(app_conf.get("Settings", "sudo_app", default=0))
 
891
        self.SetPreferWiredNetwork(app_conf.get("Settings", "prefer_wired", 
 
892
                                                default=False))
 
893
        self.SetShowNeverConnect(app_conf.get("Settings", "show_never_connect", 
 
894
                                                default=True))
 
895
        app_conf.write()
 
896
 
 
897
        if os.path.isfile(wireless_conf):
 
898
            print "Wireless configuration file found..."
 
899
        else:
 
900
            print "Wireless configuration file not found, creating..."
 
901
            open(wireless_conf, "w").close()
 
902
 
 
903
        if os.path.isfile(wired_conf):
 
904
            print "Wired configuration file found..."
 
905
        else:
 
906
            print "Wired configuration file not found, creating a default..."
 
907
            # Create the file and a default profile
 
908
            open(wired_conf, "w").close()
 
909
            b_wired.CreateWiredNetworkProfile("wired-default", default=True)
 
910
 
 
911
        if not os.path.isfile(dhclient_conf):
 
912
            print "dhclient.conf.template not found, copying..."
 
913
            shutil.copy(dhclient_conf + ".default", dhclient_conf)            
 
914
        # Hide the files, so the keys aren't exposed.
 
915
        print "chmoding configuration files 0600..."
 
916
        os.chmod(app_conf.get_config(), 0600)
 
917
        os.chmod(wireless_conf, 0600)
 
918
        os.chmod(wired_conf, 0600)
 
919
        os.chmod(dhclient_conf, 0644)
 
920
 
 
921
        # Make root own them
 
922
        print "chowning configuration files root:root..."
 
923
        os.chown(app_conf.get_config(), 0, 0)
 
924
        os.chown(wireless_conf, 0, 0)
 
925
        os.chown(wired_conf, 0, 0)
 
926
        os.chown(dhclient_conf, 0, 0)
 
927
 
 
928
        print "Using wireless interface..." + self.GetWirelessInterface()
 
929
        print "Using wired interface..." + self.GetWiredInterface()
 
930
 
 
931
##############################
 
932
###### Wireless Daemon #######
 
933
##############################
 
934
 
 
935
class WirelessDaemon(dbus.service.Object):
 
936
    """ DBus interface for wireless connection operations. """
 
937
    def __init__(self, bus_name, daemon, wifi=None, debug=False):
 
938
        """ Intitialize the wireless DBus interface. """
 
939
        dbus.service.Object.__init__(self, bus_name=bus_name,
 
940
                                     object_path='/org/wicd/daemon/wireless')
 
941
        self.hidden_essid = None
 
942
        self.daemon = daemon
 
943
        self.wifi = wifi
 
944
        self._debug_mode = debug
 
945
        self._scanning = False
 
946
        self.LastScan = []
 
947
        self.config = ConfigManager(wireless_conf, debug=debug)
 
948
 
 
949
    def get_debug_mode(self):
 
950
        return self._debug_mode
 
951
    def set_debug_mode(self, mode):
 
952
        self._debug_mode = mode
 
953
        self.config.debug = mode
 
954
    debug_mode = property(get_debug_mode, set_debug_mode)
 
955
 
 
956
    @dbus.service.method('org.wicd.daemon.wireless')
 
957
    def SetHiddenNetworkESSID(self, essid):
 
958
        """ Sets the ESSID of a hidden network for use with Scan(). """
 
959
        self.hidden_essid = str(misc.Noneify(essid))
 
960
 
 
961
    @dbus.service.method('org.wicd.daemon.wireless')
 
962
    def Scan(self, sync=False):
 
963
        """ Scan for wireless networks.
 
964
 
 
965
        Scans for wireless networks, optionally using a (hidden) essid
 
966
        set with SetHiddenNetworkESSID.
 
967
 
 
968
        The sync keyword argument specifies whether the scan should
 
969
        be done synchronously.
 
970
 
 
971
        """
 
972
        if self._scanning:
 
973
            if self.debug_mode:
 
974
                print "scan already in progress, skipping"
 
975
            return False
 
976
        if self.debug_mode:
 
977
            print 'scanning start'
 
978
        self.SendStartScanSignal()
 
979
        if sync:
 
980
            self._sync_scan()
 
981
        else:
 
982
            self._async_scan()
 
983
        return True
 
984
 
 
985
    @misc.threaded
 
986
    def _async_scan(self):
 
987
        """ Run a scan in its own thread. """
 
988
        self._sync_scan()
 
989
 
 
990
    def _sync_scan(self):
 
991
        """ Run a scan and send a signal when its finished. """
 
992
        scan = self.wifi.Scan(str(self.hidden_essid))
 
993
        self.LastScan = scan
 
994
        if self.debug_mode:
 
995
            print 'scanning done'
 
996
            print 'found ' + str(len(scan)) + ' networks:'
 
997
        for i, network in enumerate(scan):
 
998
            self.ReadWirelessNetworkProfile(i)
 
999
        self.SendEndScanSignal()
 
1000
 
 
1001
    @dbus.service.method('org.wicd.daemon.wireless')
 
1002
    def GetIwconfig(self):
 
1003
        """ Calls and returns the output of iwconfig"""
 
1004
        return misc.to_unicode(self.wifi.GetIwconfig())
 
1005
 
 
1006
    @dbus.service.method('org.wicd.daemon.wireless')
 
1007
    def GetNumberOfNetworks(self):
 
1008
        """ Returns number of networks. """
 
1009
        return len(self.LastScan)
 
1010
 
 
1011
    @dbus.service.method('org.wicd.daemon.wireless')
 
1012
    def GetApBssid(self):
 
1013
        """ Gets the MAC address for the active network. """
 
1014
        return self.wifi.GetBSSID()
 
1015
 
 
1016
    @dbus.service.method('org.wicd.daemon.wireless')
 
1017
    def GetCurrentBitrate(self, iwconfig):
 
1018
        """ Returns the current bitrate for the active network. """
 
1019
        return self.wifi.GetCurrentBitrate(iwconfig)
 
1020
 
 
1021
    @dbus.service.method('org.wicd.daemon.wireless')
 
1022
    def GetOperationalMode(self, iwconfig):
 
1023
        """ Returns the operational mode for the iwconfig parameter """
 
1024
        return misc.to_unicode(self.wifi.GetOperationalMode(iwconfig))
 
1025
 
 
1026
    @dbus.service.method('org.wicd.daemon.wireless')
 
1027
    def GetAvailableAuthMethods(self, iwlistauth):
 
1028
        """ Returns the operational mode for the iwlistauth parameter """
 
1029
        return misc.to_unicode(self.wifi.GetAvailableAuthMethods(iwlistauth))
 
1030
 
 
1031
    @dbus.service.method('org.wicd.daemon.wireless')
 
1032
    def CreateAdHocNetwork(self, essid, channel, ip, enctype, key, encused,
 
1033
                           ics):
 
1034
        """ Creates an ad-hoc network using user inputted settings. """
 
1035
        self.wifi.CreateAdHocNetwork(essid, channel, ip, enctype, key, encused)
 
1036
 
 
1037
    @dbus.service.method('org.wicd.daemon.wireless')
 
1038
    def GetKillSwitchEnabled(self):
 
1039
        """ Returns true if kill switch is pressed. """
 
1040
        status = self.wifi.GetKillSwitchStatus()
 
1041
        return status
 
1042
 
 
1043
    @dbus.service.method('org.wicd.daemon.wireless')
 
1044
    def SwitchRfKill(self):
 
1045
        """ Switches the rfkill on/off for wireless cards. """
 
1046
        return self.wifi.SwitchRfKill()
 
1047
 
 
1048
    @dbus.service.method('org.wicd.daemon.wireless')
 
1049
    def GetRfKillEnabled(self):
 
1050
        """ Returns true if rfkill switch is enabled. """
 
1051
        return self.wifi.GetRfKillStatus()
 
1052
 
 
1053
    @dbus.service.method('org.wicd.daemon.wireless')
 
1054
    def GetWirelessProperty(self, networkid, property):
 
1055
        """ Retrieves wireless property from the network specified """
 
1056
        try:
 
1057
            value = self.LastScan[networkid].get(property)
 
1058
        except IndexError:
 
1059
            return ""
 
1060
        value = misc.to_unicode(value)
 
1061
        return value
 
1062
 
 
1063
    @dbus.service.method('org.wicd.daemon.wireless')
 
1064
    def SetWirelessProperty(self, netid, prop, value):
 
1065
        """ Sets property to value in network specified. """
 
1066
        # We don't write script settings here.
 
1067
        prop = misc.sanitize_config(prop)
 
1068
        if prop.endswith('script'):
 
1069
            print 'Setting script properties through the daemon' \
 
1070
                  + ' is not permitted.'
 
1071
            return False
 
1072
        self.LastScan[netid][prop] = misc.to_unicode(misc.Noneify(value))
 
1073
 
 
1074
    @dbus.service.method('org.wicd.daemon.wireless')
 
1075
    def DetectWirelessInterface(self):
 
1076
        """ Returns an automatically detected wireless interface. """
 
1077
        iface = self.wifi.DetectWirelessInterface()
 
1078
        if iface:
 
1079
            print 'Automatically detected wireless interface ' + iface
 
1080
        else:
 
1081
            print "Couldn't detect a wireless interface."
 
1082
        return str(iface)
 
1083
 
 
1084
    @dbus.service.method('org.wicd.daemon.wireless')
 
1085
    def DisconnectWireless(self):
 
1086
        """ Disconnects the wireless network. """
 
1087
        self.wifi.Disconnect()
 
1088
        self.daemon.UpdateState()
 
1089
 
 
1090
    @dbus.service.method('org.wicd.daemon.wireless')
 
1091
    def IsWirelessUp(self):
 
1092
        """ Returns a boolean specifying if wireless is up or down. """
 
1093
        return self.wifi.IsUp()
 
1094
 
 
1095
    @dbus.service.method('org.wicd.daemon.wireless')
 
1096
    def GetCurrentSignalStrength(self, iwconfig=None):
 
1097
        """ Returns the current signal strength. """
 
1098
        try:
 
1099
            strength = int(self.wifi.GetSignalStrength(iwconfig))
 
1100
        except TypeError:
 
1101
            strength = 0
 
1102
        return strength
 
1103
 
 
1104
    @dbus.service.method('org.wicd.daemon.wireless')
 
1105
    def GetCurrentDBMStrength(self, iwconfig=None):
 
1106
        """ Returns the current dbm signal strength. """
 
1107
        try:
 
1108
            dbm_strength = int(self.wifi.GetDBMStrength(iwconfig))
 
1109
        except:
 
1110
            dbm_strength = 0
 
1111
        return dbm_strength
 
1112
 
 
1113
    @dbus.service.method('org.wicd.daemon.wireless')
 
1114
    def GetCurrentNetwork(self, iwconfig=None):
 
1115
        """ Returns the current network. """
 
1116
        current_network = str(self.wifi.GetCurrentNetwork(iwconfig))
 
1117
        return current_network
 
1118
 
 
1119
    @dbus.service.method('org.wicd.daemon.wireless')
 
1120
    def GetCurrentNetworkID(self, iwconfig=None):
 
1121
        """ Returns the id of the current network, or -1 if its not found. """
 
1122
        currentESSID = self.GetCurrentNetwork(iwconfig)
 
1123
        for x in xrange(0, len(self.LastScan)):
 
1124
            if self.LastScan[x]['essid'] == currentESSID:
 
1125
                return x
 
1126
        if self.debug_mode:
 
1127
            print 'GetCurrentNetworkID: Returning -1, current network not found'
 
1128
        return -1
 
1129
 
 
1130
    @dbus.service.method('org.wicd.daemon.wireless')
 
1131
    def EnableWirelessInterface(self):
 
1132
        """ Calls a method to enable the wireless interface. """
 
1133
        result = self.wifi.EnableInterface()
 
1134
        return result
 
1135
 
 
1136
    @dbus.service.method('org.wicd.daemon.wireless')
 
1137
    def DisableWirelessInterface(self):
 
1138
        """ Calls a method to disable the wireless interface. """
 
1139
        result = self.wifi.DisableInterface()
 
1140
        return result
 
1141
 
 
1142
    @dbus.service.method('org.wicd.daemon.wireless')
 
1143
    def ConnectWireless(self, id):
 
1144
        """ Connects the the wireless network specified by i"""
 
1145
        self.SaveWirelessNetworkProfile(id)
 
1146
        # Will returned instantly, that way we don't hold up dbus.
 
1147
        # CheckIfWirelessConnecting can be used to test if the connection
 
1148
        # is done.
 
1149
        self.wifi.before_script = self.GetWirelessProperty(id, 'beforescript')
 
1150
        self.wifi.after_script = self.GetWirelessProperty(id, 'afterscript')
 
1151
        self.wifi.pre_disconnect_script = self.GetWirelessProperty(id,
 
1152
                                                               'predisconnectscript')
 
1153
        self.wifi.post_disconnect_script = self.GetWirelessProperty(id,
 
1154
                                                               'postdisconnectscript')
 
1155
        print 'Connecting to wireless network ' + str(self.LastScan[id]['essid'])
 
1156
        # disconnect to make sure that scripts are run
 
1157
        self.wifi.Disconnect()
 
1158
        self.daemon.wired_bus.wired.Disconnect()
 
1159
        self.daemon.SetForcedDisconnect(False)
 
1160
        conthread = self.wifi.Connect(self.LastScan[id], debug=self.debug_mode)
 
1161
        self.daemon.UpdateState()
 
1162
 
 
1163
    @dbus.service.method('org.wicd.daemon.wireless')
 
1164
    def CheckIfWirelessConnecting(self):
 
1165
        """Returns True if wireless interface is connecting, otherwise False."""
 
1166
        if self.wifi.connecting_thread:
 
1167
            return self.wifi.connecting_thread.is_connecting
 
1168
        else:
 
1169
            return False
 
1170
 
 
1171
    @dbus.service.method('org.wicd.daemon.wireless')
 
1172
    def GetWirelessIP(self, ifconfig=""):
 
1173
        """ Returns the IP associated with the wireless interface. """
 
1174
        ip = self.wifi.GetIP(ifconfig)
 
1175
        return ip
 
1176
 
 
1177
    @dbus.service.method('org.wicd.daemon.wireless')
 
1178
    def CheckWirelessConnectingStatus(self):
 
1179
        """ Returns the wireless interface's status code. """
 
1180
        if self.wifi.connecting_thread:
 
1181
            stat = self.wifi.connecting_thread.GetStatus()
 
1182
            return stat
 
1183
        else:
 
1184
            return False
 
1185
 
 
1186
    @dbus.service.method('org.wicd.daemon.wireless')
 
1187
    def CheckWirelessConnectingMessage(self):
 
1188
        """ Returns the wireless interface's status message. """
 
1189
        if self.wifi.connecting_thread:
 
1190
            stat = self.CheckWirelessConnectingStatus()
 
1191
            return _status_dict[stat]
 
1192
        else:
 
1193
            return False
 
1194
 
 
1195
    @dbus.service.method('org.wicd.daemon.wireless')
 
1196
    def ReadWirelessNetworkProfile(self, id):
 
1197
        """ Reads in wireless profile as the active network """
 
1198
        cur_network = self.LastScan[id]
 
1199
        essid_key = "essid:%s" % cur_network["essid"]
 
1200
        bssid_key = cur_network["bssid"]
 
1201
 
 
1202
        if self.config.get(essid_key, 'use_settings_globally'):
 
1203
            section = essid_key
 
1204
        elif self.config.has_section(bssid_key):
 
1205
            section = bssid_key
 
1206
        else:
 
1207
            return "500: Profile Not Found"
 
1208
 
 
1209
        for x in self.config.options(section):
 
1210
            if not cur_network.has_key(x) or x.endswith("script"):
 
1211
                cur_network[x] = misc.Noneify(self.config.get(section, x))
 
1212
        for option in ['use_static_dns', 'use_global_dns', 'encryption',
 
1213
                       'use_settings_globally']:
 
1214
            cur_network[option] = bool(cur_network.get(option))
 
1215
        # Read the essid because we need to name those hidden
 
1216
        # wireless networks now - but only read it if it is hidden.
 
1217
        if cur_network["hidden"]:
 
1218
            # check if there is an essid in the config file
 
1219
            # if there isn't, .get( will return None
 
1220
            stored_essid = self.config.get(section, 'essid')
 
1221
            if stored_essid:
 
1222
                # set the current network's ESSID to the stored one
 
1223
                cur_network['essid'] = stored_essid
 
1224
 
 
1225
    @dbus.service.method('org.wicd.daemon.wireless')
 
1226
    def SaveWirelessNetworkProfile(self, id):
 
1227
        """ Writes a wireless profile to disk. """
 
1228
        def write_script_ent(prof, script):
 
1229
            if not self.config.has_option(prof, script):
 
1230
                self.config.set(prof, script, None)
 
1231
 
 
1232
        cur_network = self.LastScan[id]
 
1233
        bssid_key = cur_network["bssid"]
 
1234
        essid_key = "essid:%s" % cur_network["essid"]
 
1235
 
 
1236
        self.config.remove_section(bssid_key)
 
1237
        self.config.add_section(bssid_key)
 
1238
 
 
1239
        # We want to write the essid in addition to bssid
 
1240
        # sections if global settings are enabled.
 
1241
        self.config.remove_section(essid_key)
 
1242
        if cur_network.get("use_settings_globally", False):
 
1243
            self.config.add_section(essid_key)
 
1244
 
 
1245
        for x in cur_network:
 
1246
            # There's no reason to save these to a configfile...
 
1247
            if x not in ['quality', 'strength', 'bitrates', 'has_profile']:
 
1248
                self.config.set(bssid_key, x, cur_network[x])
 
1249
                if cur_network.get("use_settings_globally", False):
 
1250
                    self.config.set(essid_key, x, cur_network[x])
 
1251
 
 
1252
        write_script_ent(bssid_key, "beforescript")
 
1253
        write_script_ent(bssid_key, "afterscript")
 
1254
        write_script_ent(bssid_key, "predisconnectscript")
 
1255
        write_script_ent(bssid_key, "postdisconnectscript")
 
1256
 
 
1257
        if cur_network.get("use_settings_globally", False):
 
1258
            write_script_ent(essid_key, "beforescript")
 
1259
            write_script_ent(essid_key, "afterscript")
 
1260
            write_script_ent(essid_key, "predisconnectscript")
 
1261
            write_script_ent(essid_key, "postdisconnectscript")
 
1262
 
 
1263
        self.config.write()
 
1264
 
 
1265
    @dbus.service.method('org.wicd.daemon.wireless')
 
1266
    def SaveWirelessNetworkProperty(self, id, option):
 
1267
        """ Writes a particular wireless property to disk. """
 
1268
        option = misc.sanitize_config(option)
 
1269
        if option.endswith("script"):
 
1270
            print 'You cannot save script information to disk through ' + \
 
1271
                  'the daemon.'
 
1272
            return
 
1273
        config = self.config
 
1274
        cur_network = self.LastScan[id]
 
1275
        essid_key = "essid:" + cur_network["essid"]
 
1276
 
 
1277
        config.set(cur_network["bssid"], option, str(cur_network[option]))
 
1278
 
 
1279
        # Write the global section as well, if required.
 
1280
        if config.get(essid_key, 'use_settings_globally'):
 
1281
            config.set(essid_key, option, str(cur_network[option]))
 
1282
        config.write()
 
1283
 
 
1284
    @dbus.service.method('org.wicd.daemon.wireless')
 
1285
    def RemoveGlobalEssidEntry(self, networkid):
 
1286
        """ Removes the global entry for the networkid provided. """
 
1287
        essid_key = "essid:" + str(self.LastScan[networkid])
 
1288
        self.config.remove_section(essid_key)
 
1289
 
 
1290
    @dbus.service.method('org.wicd.daemon.wireless')
 
1291
    def GetWpaSupplicantDrivers(self):
 
1292
        """ Returns all valid wpa_supplicant drivers. """
 
1293
        return self.wifi.GetWpaSupplicantDrivers()
 
1294
 
 
1295
    @dbus.service.method('org.wicd.daemon.wireless')
 
1296
    def ReloadConfig(self):
 
1297
        """ Reloads the active config file. """
 
1298
        self.config.reload()
 
1299
 
 
1300
    @dbus.service.method('org.wicd.daemon.wireless')
 
1301
    def GetWirelessInterfaces(self):
 
1302
        ''' Returns a list of wireless interfaces on the system. '''
 
1303
        return wnettools.GetWirelessInterfaces()
 
1304
 
 
1305
    @dbus.service.signal(dbus_interface='org.wicd.daemon.wireless', signature='')
 
1306
    def SendStartScanSignal(self):
 
1307
        """ Emits a signal announcing a scan has started. """
 
1308
        self._scanning = True
 
1309
 
 
1310
    @dbus.service.signal(dbus_interface='org.wicd.daemon.wireless', signature='')
 
1311
    def SendEndScanSignal(self):
 
1312
        """ Emits a signal announcing a scan has finished. """
 
1313
        self._scanning = False
 
1314
 
 
1315
    def _wireless_autoconnect(self, fresh=True):
 
1316
        """ Attempts to autoconnect to a wireless network. """
 
1317
        print "No wired connection present, attempting to autoconnect " + \
 
1318
              "to wireless network"
 
1319
        if self.wifi.wireless_interface is None:
 
1320
            print 'Autoconnect failed because wireless interface returned None'
 
1321
            return
 
1322
        if fresh:
 
1323
            self.Scan(sync=True)
 
1324
 
 
1325
        for x, network in enumerate(self.LastScan):
 
1326
            if self.config.has_section(network['bssid']):
 
1327
                if self.debug_mode:
 
1328
                    print network["essid"] + ' has profile'
 
1329
                if bool(network.get('automatic')):
 
1330
                    try:
 
1331
                        if network.get('never'):
 
1332
                            print network["essid"],'marked never connect'
 
1333
                            continue
 
1334
                    except:
 
1335
                        print network["essid"],'has no never connect value'
 
1336
                    print 'trying to automatically connect to...' + \
 
1337
                          network["essid"]
 
1338
                    self.ConnectWireless(x)
 
1339
                    time.sleep(1)
 
1340
                    return
 
1341
        print "Unable to autoconnect, you'll have to manually connect"
 
1342
 
 
1343
###########################
 
1344
###### Wired Daemon #######
 
1345
###########################
 
1346
 
 
1347
class WiredDaemon(dbus.service.Object):
 
1348
    """ DBus interface for wired connection operations. """
 
1349
    def __init__(self, bus_name, daemon, wired=None, debug=False):
 
1350
        """ Intitialize the wireless DBus interface. """
 
1351
        dbus.service.Object.__init__(self, bus_name=bus_name,
 
1352
                                     object_path="/org/wicd/daemon/wired")
 
1353
        self.daemon = daemon
 
1354
        self.wired = wired
 
1355
        self._debug_mode = debug
 
1356
        self._cur_wired_prof_name = ""
 
1357
        self.WiredNetwork = {}
 
1358
        self.config = ConfigManager(wired_conf, debug=debug)
 
1359
 
 
1360
    def get_debug_mode(self):
 
1361
        return self._debug_mode
 
1362
    def set_debug_mode(self, mode):
 
1363
        self._debug_mode = mode
 
1364
        self.config.debug = mode
 
1365
    debug_mode = property(get_debug_mode, set_debug_mode)
 
1366
 
 
1367
    @dbus.service.method('org.wicd.daemon.wired')
 
1368
    def GetWiredIP(self, ifconfig=""):
 
1369
        """ Returns the wired interface's ip address. """
 
1370
        ip = self.wired.GetIP(ifconfig)
 
1371
        return ip
 
1372
 
 
1373
    @dbus.service.method('org.wicd.daemon.wired')
 
1374
    def CheckIfWiredConnecting(self):
 
1375
        """ Returns True if wired interface is connecting, otherwise False. """
 
1376
        if self.wired.connecting_thread:
 
1377
            return self.wired.connecting_thread.is_connecting
 
1378
        else:
 
1379
            return False
 
1380
 
 
1381
    @dbus.service.method('org.wicd.daemon.wired')
 
1382
    def CheckWiredConnectingStatus(self):
 
1383
        """Returns the wired interface's status code. '"""
 
1384
        if self.wired.connecting_thread:
 
1385
            return self.wired.connecting_thread.GetStatus()
 
1386
        else:
 
1387
            return False
 
1388
 
 
1389
    @dbus.service.method('org.wicd.daemon.wired')
 
1390
    def CheckWiredConnectingMessage(self):
 
1391
        """ Returns the wired interface's status message. """
 
1392
        if self.wired.connecting_thread:
 
1393
            return _status_dict[self.CheckWiredConnectingStatus()]
 
1394
        else:
 
1395
            return False
 
1396
 
 
1397
    @dbus.service.method('org.wicd.daemon.wired')
 
1398
    def DetectWiredInterface(self):
 
1399
        """ Returns an automatically detected wireless interface. """
 
1400
        iface = self.wired.DetectWiredInterface()
 
1401
        if iface:
 
1402
            print 'automatically detected wired interface ' + str(iface)
 
1403
        else:
 
1404
            print "Couldn't detect a wired interface."
 
1405
        return str(iface)
 
1406
 
 
1407
    @dbus.service.method('org.wicd.daemon.wired')
 
1408
    def SetWiredProperty(self, prop, value):
 
1409
        """ Sets the given property to the given value. """
 
1410
        if self.WiredNetwork:
 
1411
            prop = misc.sanitize_config(prop)
 
1412
            if prop.endswith('script'):
 
1413
                print 'Setting script properties through the daemon' \
 
1414
                      + ' is not permitted.'
 
1415
                return False
 
1416
            self.WiredNetwork[prop] = misc.to_unicode(misc.Noneify(value))
 
1417
            return True
 
1418
        else:
 
1419
            print 'SetWiredProperty: WiredNetwork does not exist'
 
1420
            return False
 
1421
 
 
1422
    @dbus.service.method('org.wicd.daemon.wired')
 
1423
    def GetWiredProperty(self, property):
 
1424
        """ Returns the requested wired property. """
 
1425
        if self.WiredNetwork:
 
1426
            value = self.WiredNetwork.get(property)
 
1427
            return value
 
1428
        else:
 
1429
            print 'GetWiredProperty: WiredNetwork does not exist'
 
1430
            return False
 
1431
 
 
1432
    @dbus.service.method('org.wicd.daemon.wired')
 
1433
    def HasWiredDriver(self):
 
1434
        """ Returns True if a driver is associated with this interface. """
 
1435
        if self.wired.driver:
 
1436
            return True
 
1437
        else:
 
1438
            return False
 
1439
 
 
1440
    @dbus.service.method('org.wicd.daemon.wired')
 
1441
    def DisconnectWired(self):
 
1442
        """ Disconnects the wired network. """
 
1443
        self.wired.Disconnect()
 
1444
        self.daemon.UpdateState()
 
1445
 
 
1446
    @dbus.service.method('org.wicd.daemon.wired')
 
1447
    def CheckPluggedIn(self):
 
1448
        """ Returns True if a ethernet cable is present, False otherwise. """
 
1449
        if self.wired.wired_interface and self.wired.wired_interface != "None":
 
1450
            return self.wired.CheckPluggedIn()
 
1451
        else:
 
1452
            return None
 
1453
 
 
1454
    @dbus.service.method('org.wicd.daemon.wired')
 
1455
    def IsWiredUp(self):
 
1456
        """ Returns a boolean specifying if wired iface is up or down. """
 
1457
        return self.wired.IsUp()
 
1458
 
 
1459
    @dbus.service.method('org.wicd.daemon.wired')
 
1460
    def EnableWiredInterface(self):
 
1461
        """ Calls a method to enable the wired interface. """           
 
1462
        return self.wired.EnableInterface()
 
1463
 
 
1464
    @dbus.service.method('org.wicd.daemon.wired')
 
1465
    def DisableWiredInterface(self):
 
1466
        """ Calls a method to disable the wired interface. """
 
1467
        return self.wired.DisableInterface()
 
1468
 
 
1469
    @dbus.service.method('org.wicd.daemon.wired')
 
1470
    def ConnectWired(self):
 
1471
        """ Connects to a wired network. """
 
1472
        self.wired.before_script = self.GetWiredProperty("beforescript")
 
1473
        self.wired.after_script = self.GetWiredProperty("afterscript")
 
1474
        self.wired.pre_disconnect_script = self.GetWiredProperty("predisconnectscript")
 
1475
        self.wired.post_disconnect_script = self.GetWiredProperty("postdisconnectscript")
 
1476
        self.daemon.wireless_bus.wifi.Disconnect()
 
1477
        # make sure disconnect scripts are run
 
1478
        self.wired.Disconnect()
 
1479
        self.daemon.SetForcedDisconnect(False)
 
1480
        self.UnsetWiredLastUsed()
 
1481
        self.config.set(self._cur_wired_prof_name, "lastused", True, write=True)
 
1482
        self.wired.Connect(self.WiredNetwork, debug=self.debug_mode)
 
1483
        self.daemon.UpdateState()
 
1484
 
 
1485
    @dbus.service.method('org.wicd.daemon.wired')
 
1486
    def CreateWiredNetworkProfile(self, profilename, default=False):
 
1487
        """ Creates a wired network profile. """
 
1488
        if not profilename:
 
1489
            return False
 
1490
        profilename = misc.to_unicode(profilename)
 
1491
        print "Creating wired profile for " + profilename
 
1492
        if self.config.has_section(profilename):
 
1493
            return False
 
1494
 
 
1495
        for option in ["ip", "broadcast", "netmask", "gateway", "search_domain", 
 
1496
                       "dns_domain", "dns1", "dns2", "dns3", "beforescript", 
 
1497
                       "afterscript", "predisconnectscript",
 
1498
                       "postdisconnectscript", "encryption_enabled"]:
 
1499
            self.config.set(profilename, option, None)
 
1500
        self.config.set(profilename, "default", default)
 
1501
        self.config.set(profilename,"dhcphostname",os.uname()[1])
 
1502
        self.config.write()
 
1503
        return True
 
1504
 
 
1505
    @dbus.service.method('org.wicd.daemon.wired')
 
1506
    def UnsetWiredLastUsed(self):
 
1507
        """ Finds the previous lastused network, and sets lastused to False. """
 
1508
        profileList = self.config.sections()
 
1509
        for profile in profileList:
 
1510
            if misc.to_bool(self.config.get(profile, "lastused")):
 
1511
                self.config.set(profile, "lastused", False, write=True)
 
1512
 
 
1513
    @dbus.service.method('org.wicd.daemon.wired')
 
1514
    def UnsetWiredDefault(self):
 
1515
        """ Unsets the default option in the current default wired profile. """
 
1516
        profileList = self.config.sections()
 
1517
        for profile in profileList:
 
1518
            if misc.to_bool(self.config.get(profile, "default")):
 
1519
                self.config.set(profile, "default", False, write=True)
 
1520
 
 
1521
    @dbus.service.method('org.wicd.daemon.wired')
 
1522
    def GetDefaultWiredNetwork(self):
 
1523
        """ Returns the current default wired network. """
 
1524
        profileList = self.config.sections()
 
1525
        for profile in profileList:
 
1526
            if misc.to_bool(self.config.get(profile, "default")):
 
1527
                return profile
 
1528
        return None
 
1529
 
 
1530
    @dbus.service.method('org.wicd.daemon.wired')
 
1531
    def GetLastUsedWiredNetwork(self):
 
1532
        """ Returns the profile of the last used wired network. """
 
1533
        profileList = self.config.sections()
 
1534
        for profile in profileList:
 
1535
            if misc.to_bool(self.config.get(profile, "lastused")):
 
1536
                return profile
 
1537
        return None
 
1538
 
 
1539
    @dbus.service.method('org.wicd.daemon.wired')
 
1540
    def DeleteWiredNetworkProfile(self, profilename):
 
1541
        """ Deletes a wired network profile. """
 
1542
        profilename = misc.to_unicode(profilename)
 
1543
        print "Deleting wired profile for " + str(profilename)
 
1544
        self.config.remove_section(profilename)
 
1545
        self.config.write()
 
1546
 
 
1547
    @dbus.service.method('org.wicd.daemon.wired')
 
1548
    def SaveWiredNetworkProfile(self, profilename):
 
1549
        """ Writes a wired network profile to disk. """
 
1550
        def write_script_ent(prof, script):
 
1551
            if not self.config.has_option(prof, script):
 
1552
                self.config.set(prof, script, None)
 
1553
 
 
1554
        profilename = profilename.strip()
 
1555
        if not profilename:
 
1556
            self.config.write()
 
1557
            print "Warning: Bad wired profile name given, ignoring."
 
1558
            return "500: Bad Profile name"
 
1559
        if self.debug_mode:
 
1560
            print "saving wired profile %s" % profilename
 
1561
        profilename = misc.to_unicode(profilename)
 
1562
        self.config.remove_section(profilename)
 
1563
        self.config.add_section(profilename)
 
1564
        for x in self.WiredNetwork:
 
1565
            self.config.set(profilename, x, self.WiredNetwork[x])
 
1566
 
 
1567
        write_script_ent(profilename, "beforescript")
 
1568
        write_script_ent(profilename, "afterscript")
 
1569
        write_script_ent(profilename, "predisconnectscript")
 
1570
        write_script_ent(profilename, "postdisconnectscript")
 
1571
        self.config.write()
 
1572
        return "100: Profile Written"
 
1573
 
 
1574
    @dbus.service.method('org.wicd.daemon.wired')
 
1575
    def ReadWiredNetworkProfile(self, profilename):
 
1576
        """ Reads a wired network profile in as the currently active profile """
 
1577
        profile = {}
 
1578
        profilename = misc.to_unicode(profilename)
 
1579
        if self.config.has_section(profilename):
 
1580
            if self.debug_mode:
 
1581
                print "Reading wired profile %s" % profilename
 
1582
            for x in self.config.options(profilename):
 
1583
                profile[x] = misc.Noneify(self.config.get(profilename, x))
 
1584
            profile['use_global_dns'] = bool(profile.get('use_global_dns'))
 
1585
            profile['use_static_dns'] = bool(profile.get('use_static_dns'))
 
1586
            profile['encryption_enabled'] = bool(profile.get('encryption_enabled'))
 
1587
            profile['profilename'] = profilename
 
1588
            self.WiredNetwork = profile
 
1589
            self._cur_wired_prof_name = profilename
 
1590
            return "100: Loaded Profile"
 
1591
        else:
 
1592
            self._cur_wired_prof_name = ""
 
1593
            self.WiredNetwork = {}
 
1594
            return "500: Profile Not Found"
 
1595
 
 
1596
    @dbus.service.method('org.wicd.daemon.wired')
 
1597
    def GetWiredProfileList(self):
 
1598
        """ Returns a list of all wired profiles in wired-settings.conf. """
 
1599
        sections = self.config.sections()
 
1600
        if not sections:
 
1601
            sections = [""]
 
1602
        return sections
 
1603
 
 
1604
    @dbus.service.method('org.wicd.daemon.wired')
 
1605
    def ReloadConfig(self):
 
1606
        """ Reloads the active config file. """
 
1607
        self.config.reload()
 
1608
 
 
1609
    @dbus.service.method('org.wicd.daemon.wired')
 
1610
    def GetWiredInterfaces(self):
 
1611
        ''' Returns a list of wireless interfaces on the system. '''
 
1612
        return wnettools.GetWiredInterfaces()
 
1613
 
 
1614
def usage():
 
1615
    print """
 
1616
wicd %s 
 
1617
wireless (and wired) connection daemon.
 
1618
 
 
1619
Arguments:
 
1620
\t-a\t--no-autoconnect\tDon't auto-scan/auto-connect.
 
1621
\t-f\t--no-daemon\tDon't daemonize (run in foreground).
 
1622
\t-e\t--no-stderr\tDon't redirect stderr.
 
1623
\t-n\t--no-poll\tDon't monitor network status.
 
1624
\t-o\t--no-stdout\tDon't redirect stdout.
 
1625
\t-h\t--help\t\tPrint this help.
 
1626
""" % (wpath.version + ' (bzr-r%s)' % wpath.revision)
 
1627
 
 
1628
def daemonize():
 
1629
    """ Disconnect from the controlling terminal.
 
1630
 
 
1631
    Fork twice, once to disconnect ourselves from the parent terminal and a
 
1632
    second time to prevent any files we open from becoming our controlling
 
1633
    terminal.
 
1634
 
 
1635
    For more info see:
 
1636
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
 
1637
 
 
1638
    """
 
1639
    # Fork the first time to disconnect from the parent terminal and
 
1640
    # exit the parent process.
 
1641
    try:
 
1642
        pid = os.fork()
 
1643
        if pid > 0:
 
1644
            sys.exit(0)
 
1645
    except OSError, e:
 
1646
        print >> sys.stderr, "Fork #1 failed: %d (%s)" % (e.errno, e.strerror)
 
1647
        sys.exit(1)
 
1648
 
 
1649
    # Decouple from parent environment to stop us from being a zombie.
 
1650
    os.setsid()
 
1651
 
 
1652
    # Fork the second time to prevent us from opening a file that will
 
1653
    # become our controlling terminal.
 
1654
    try:
 
1655
        pid = os.fork()
 
1656
        if pid > 0:
 
1657
            dirname = os.path.dirname(wpath.pidfile)
 
1658
            if not os.path.exists(dirname):
 
1659
                os.makedirs(dirname)
 
1660
            pidfile = open(wpath.pidfile, 'w')
 
1661
            pidfile.write(str(pid) + '\n')
 
1662
            pidfile.close()
 
1663
            sys.exit(0)
 
1664
        else:
 
1665
            os.umask(0)
 
1666
            os.chdir('/')
 
1667
    except OSError, e:
 
1668
        print >> sys.stderr, "Fork #2 failed: %d (%s)" % (e.errno, e.strerror)
 
1669
        sys.exit(1)
 
1670
 
 
1671
    sys.stdin.close()
 
1672
    sys.stdout.close()
 
1673
    sys.stderr.close()
 
1674
 
 
1675
    try:
 
1676
        maxfd = os.sysconf("SC_OPEN_MAX")
 
1677
    except (AttributeError, ValueError):
 
1678
        maxfd = 1024
 
1679
       
 
1680
    for fd in range(0, maxfd):
 
1681
        try:
 
1682
            os.close(fd)
 
1683
        except OSError:
 
1684
            pass
 
1685
 
 
1686
    os.open(os.devnull, os.O_RDWR)
 
1687
 
 
1688
    # Duplicate standard input to standard output and standard error.
 
1689
    os.dup2(0, 1)
 
1690
    os.dup2(0, 2)
 
1691
 
 
1692
 
 
1693
def main(argv):
 
1694
    """ The main daemon program.
 
1695
 
 
1696
    Keyword arguments:
 
1697
    argv -- The arguments passed to the script.
 
1698
 
 
1699
    """
 
1700
    # back up resolv.conf before we do anything else
 
1701
    try:
 
1702
        backup_location = wpath.varlib + 'resolv.conf.orig'
 
1703
        # don't back up if .orig exists, probably there cause
 
1704
        # wicd exploded
 
1705
        if not os.path.exists(backup_location):
 
1706
            shutil.copy2('/etc/resolv.conf', backup_location)
 
1707
            os.chmod(backup_location, 0644)
 
1708
    except IOError:
 
1709
        print 'error backing up resolv.conf'
 
1710
 
 
1711
    do_daemonize = True
 
1712
    redirect_stderr = True
 
1713
    redirect_stdout = True
 
1714
    auto_connect = True
 
1715
    kill = False
 
1716
 
 
1717
    try:
 
1718
        opts, args = getopt.getopt(sys.argv[1:], 'fenoahk',
 
1719
                                   ['help', 'no-daemon', 'no-poll', 'no-stderr', 'no-stdout',
 
1720
                                    'no-autoconnect', 'kill'])
 
1721
    except getopt.GetoptError:
 
1722
        # Print help information and exit
 
1723
        usage()
 
1724
        sys.exit(2)
 
1725
 
 
1726
    no_poll = False
 
1727
    for o, a in opts:
 
1728
        if o in ('-h', '--help'):
 
1729
            usage()
 
1730
            sys.exit()
 
1731
        if o in ('-e', '--no-stderr'):
 
1732
            redirect_stderr = False
 
1733
        if o in ('-o', '--no-stdout'):
 
1734
            redirect_stdout = False
 
1735
        if o in ('-f', '--no-daemon'):
 
1736
            do_daemonize = False
 
1737
        if o in ('-a', '--no-autoconnect'):
 
1738
            auto_connect = False
 
1739
        if o in ('-n', '--no-poll'):
 
1740
            no_poll = True
 
1741
        if o in ('-k', '--kill'):
 
1742
             kill = True
 
1743
 
 
1744
    if kill:
 
1745
        try:
 
1746
            f = open(wpath.pidfile)
 
1747
        except:
 
1748
            #print >> sys.stderr, "No wicd instance active, aborting."
 
1749
            sys.exit(1)
 
1750
 
 
1751
        # restore resolv.conf on quit
 
1752
        try:
 
1753
            shutil.move(wpath.varlib + 'resolv.conf.orig', '/etc/resolv.conf')
 
1754
            os.chmod('/etc/resolv.conf', 0644)
 
1755
        except IOError:
 
1756
            print 'error restoring resolv.conf'
 
1757
 
 
1758
        # connect to dbus, trigger a disconnect, then knock out the daemon
 
1759
        from wicd import dbusmanager
 
1760
        bus = dbusmanager.connect_to_dbus()
 
1761
        dbus_ifaces = dbusmanager.get_dbus_ifaces()
 
1762
        dbus_ifaces['daemon'].Disconnect()
 
1763
        pid = int(f.readline())
 
1764
        f.close()
 
1765
        os.kill(pid,signal.SIGTERM)
 
1766
 
 
1767
        # quit, this should be the only option specified
 
1768
        sys.exit(0)
 
1769
 
 
1770
    if os.path.exists(wpath.pidfile):
 
1771
        print 'It seems like the daemon is already running.'
 
1772
        print 'If it is not, please remove %s and try again.' % wpath.pidfile
 
1773
        sys.exit(1)
 
1774
 
 
1775
    if not os.path.exists(wpath.networks):
 
1776
        os.makedirs(wpath.networks)
 
1777
   
 
1778
    if do_daemonize: daemonize()
 
1779
 
 
1780
    if redirect_stderr or redirect_stdout:
 
1781
        logpath = os.path.join(wpath.log, 'wicd.log')
 
1782
        if not os.path.exists(wpath.log):
 
1783
            os.makedirs(wpath.log)
 
1784
            os.chmod(wpath.log, 0755)
 
1785
        output = ManagedStdio(logpath)
 
1786
        if os.path.exists(logpath):
 
1787
            try:
 
1788
                os.chmod(logpath, int(wpath.log_perms,8))
 
1789
            except:
 
1790
                print 'unable to chmod log file to %s' % wpath.log_perms
 
1791
 
 
1792
            try:
 
1793
                if wpath.log_group:
 
1794
                    import grp
 
1795
                    group = grp.getgrnam(wpath.log_group)
 
1796
                    os.chown(logpath, 0, group[2])
 
1797
            except:
 
1798
                print 'unable to chown log file to %s' % group[2]
 
1799
 
 
1800
    if redirect_stdout: sys.stdout = output
 
1801
    if redirect_stderr: sys.stderr = output
 
1802
 
 
1803
    print '---------------------------'
 
1804
    print 'wicd initializing...'
 
1805
    print '---------------------------'
 
1806
 
 
1807
    print 'wicd is version', wpath.version, wpath.revision
 
1808
 
 
1809
    # Open the DBUS session
 
1810
    bus = dbus.SystemBus()
 
1811
    wicd_bus = dbus.service.BusName('org.wicd.daemon', bus=bus)
 
1812
    daemon = WicdDaemon(wicd_bus, auto_connect=auto_connect)
 
1813
    child_pid = None
 
1814
    if not no_poll:
 
1815
        child_pid = Popen([wpath.python, "-O", 
 
1816
                          os.path.join(wpath.daemon, "monitor.py")],
 
1817
                          shell=False, close_fds=True).pid
 
1818
    atexit.register(on_exit, child_pid)
 
1819
 
 
1820
    # Enter the main loop
 
1821
    mainloop = gobject.MainLoop()
 
1822
    try:
 
1823
        mainloop.run()
 
1824
    except KeyboardInterrupt:
 
1825
        pass
 
1826
    daemon.DaemonClosing()
 
1827
 
 
1828
def on_exit(child_pid):
 
1829
    """ Called when a SIGTERM is caught, kills monitor.py before exiting. """
 
1830
    if child_pid:
 
1831
        print 'Daemon going down, killing wicd-monitor...'
 
1832
        try:
 
1833
            os.kill(child_pid, signal.SIGTERM)
 
1834
        except OSError:
 
1835
            pass
 
1836
    print 'Removing PID file...'
 
1837
    if os.path.exists(wpath.pidfile):
 
1838
        os.remove(wpath.pidfile)
 
1839
    print 'Shutting down...'
 
1840
    sys.exit(0)
 
1841
 
 
1842
 
 
1843
if __name__ == '__main__':
 
1844
    if os.getuid() != 0:
 
1845
        print ("Root privileges are required for the daemon to run properly." +
 
1846
               "  Exiting.")
 
1847
        sys.exit(1)
 
1848
    gobject.threads_init()
 
1849
    main(sys.argv)