import sys
import re
import os
import select
import time
import signal
import glob
import libxml2
import chestnut_dialer
from chestnut_dialer import _
from chestnut_dialer import debug_msg
import chestnut_dialer.dobj
dobj = chestnut_dialer.dobj
from chestnut_dialer.dobj.server import UnixDObjServer
from chestnut_dialer.xml_account_set import XmlAccount,XmlAccountSet
from chestnut_dialer.xml_config import XmlConfig
server = None
class Session:
pid = None
start_time = None
def __init__(self, pid):
self.pid = pid
self.start_time = time.time()
class SharedData:
accounts = None
config = None
def __init__(self):
user_config_dir = chestnut_dialer.user_config_dir
self.config_file = chestnut_dialer.config_file
self.accounts_file = chestnut_dialer.accounts_file
if not os.access(user_config_dir, os.F_OK):
os.mkdir(user_config_dir)
os.chmod(user_config_dir, 0700)
if not os.access(self.config_file, os.F_OK):
f = open(chestnut_dialer.def_config_file)
text = re.sub(r'<!--(.|\n)*?-->', '', f.read())
f.close()
f = open(self.config_file, "w")
f.write(text)
f.close()
os.chmod(self.config_file, 0600)
if not os.access(self.accounts_file, os.F_OK):
f = open(chestnut_dialer.def_accounts_file)
text = re.sub(r'<!--(.|\n)*?-->', '', f.read())
f.close()
f = open(self.accounts_file, "w")
f.write(text)
f.close()
os.chmod(self.accounts_file, 0600)
self._accounts_changed = 0
self._accounts_xml = libxml2.parseFile(self.accounts_file)
self.accounts = XmlAccountSet(
self._accounts_xml.xpathEval("/account-list")[0],
(self.on_accounts_changed,))
self._config_changed = 0
self._config_xml = libxml2.parseFile(self.config_file)
self.config = XmlConfig(
self._config_xml.xpathEval("/config")[0],
(self.on_config_changed,))
self.config.attr_changed_signal.append(self.on_config_attr_changed)
self._sessions = {}
def __del__(self):
if self._config_changed:
self._config_xml.saveFormatFile(self.config_file, 1)
self._config_xml.freeDoc()
if self._accounts_changed:
self._accounts_xml.saveFormatFile(self.accounts_file, 1)
self._accounts_xml.freeDoc()
def remove_signal_callbacks(self):
self.accounts.changed_signal.remove(self.on_accounts_changed)
self.config.changed_signal.remove(self.on_config_changed)
self.config.attr_changed_signal.remove(self.on_config_attr_changed)
def on_accounts_changed(self):
self._accounts_changed = 1
if server != None: server.push_event(dobj.SimpleEvent(
("accounts-changed",)))
def on_config_changed(self):
self._config_changed = 1
def on_config_attr_changed(self, name, value):
if server != None: server.push_event(dobj.SimpleEvent(
("config-attr-changed", name, value)))
def new_session(self, pid):
session = Session(pid)
self._sessions.update({pid: session})
return session
def get_session(self, pid):
return self._sessions[pid]
def ls_sessions(self):
return tuple(self._sessions.keys())
def remove_session(self, pid):
del self._sessions[pid]
exit_signal_emited = 0
def exit_signal_handler(signum, stackframe):
global exit_signal_emited
debug_msg(_("interrupted by signal %d") % signum, 3)
exit_signal_emited = 1
# main code
# check if socket already exists
if os.access(chestnut_dialer.session_socket, os.F_OK):
debug_msg(_("session socket already exists"), 0)
sys.exit(chestnut_dialer.EX_SOFTWARE)
# create pid file
try:
open(chestnut_dialer.session_pid_file, 'w').write(str(os.getpid()))
except IOError:
debug_msg(_("cannot create pid file: %s") %
chestnut_dialer.session_pid_file, 0)
sys.exit(chestnut_dialer.EX_OSERR)
# setup signal handler
signal.signal(signal.SIGINT, exit_signal_handler)
signal.signal(signal.SIGTERM, exit_signal_handler)
signal.signal(signal.SIGHUP, exit_signal_handler)
chestnut_dialer.init_locale()
server = UnixDObjServer(chestnut_dialer.session_socket, SharedData())
server.direct_result_for_call += [
(XmlAccount, "copy"),
(XmlAccount, "get_attr_type_dict"),
(XmlAccountSet, "ls_accounts"),
]
try: exit_timeout = int(sys.argv[1])
except IndexError: exit_timeout = 30
except ValueError: exit_timeout = 30
for fn in glob.glob(chestnut_dialer.session_wait_base + '*'):
try:
f = open(fn, 'w')
f.write('startup')
f.close()
except IOError: pass
while not exit_signal_emited:
try: rfds = select.select([server.fileno()], [], [], exit_timeout)[0]
except select.error: rfds = []
if rfds: server.handle_request()
elif not server.root_object.ls_sessions(): break
server.root_object.remove_signal_callbacks()
try: os.remove(chestnut_dialer.session_pid_file)
except OSError:
debug_msg(_("cannot remove pid file: %s") %
chestnut_dialer.session_pid_file, 1)
|