Package dogtail :: Module sessions
[hide private]
[frames] | no frames]

Source Code for Module dogtail.sessions

  1  import time 
  2  import os 
  3  import errno 
  4  import re 
  5  import subprocess 
  6  import signal 
  7  import tempfile 
  8  import random 
  9  import glob 
 10  from dogtail.config import config 
11 12 -def scratchFile(label):
13 """Uses tempfile.NamedTemporaryFile() to create a unique tempfile in 14 config.scratchDir, with a filename like: 15 dogtail-headless-<label>.<random junk>""" 16 prefix = "dogtail-headless-" 17 return tempfile.NamedTemporaryFile(prefix = "%s%s." % (prefix, label), 18 dir = config.scratchDir)
19
20 -def testBinary(path):
21 if (path.startswith(os.path.sep) or 22 path.startswith(os.path.join('.','')) or 23 path.startswith(os.path.join('..',''))): 24 if not os.path.exists(path): 25 raise IOError, (errno.ENOENT, "No such file", path) 26 if not os.access(path, os.X_OK): 27 raise IOError, (errno.ENOEXEC, "Permission denied", path) 28 return True
29
30 -class Subprocess(object):
31 - def __init__(self, cmdList, environ = None):
32 testBinary(cmdList[0]) 33 self.cmdList = cmdList 34 self.environ = environ 35 self._exitCode = None
36
37 - def start(self):
38 if self.environ == None: environ = os.environ 39 self.popen = subprocess.Popen(self.cmdList, 40 env = self.environ)#, stdout = subprocess.PIPE, 41 #stderr = subprocess.STDOUT, close_fds = True) 42 return self.popen.pid
43
44 - def wait(self):
45 return self.popen.wait()
46
47 - def stop(self):
48 # The following doesn't exist in python < 2.6, if you can believe it. 49 #self.popen.terminate() 50 os.kill(self.popen.pid, signal.SIGTERM)
51 52 @property
53 - def exitCode(self):
54 if self._exitCode == None: 55 self._exitCode = self.wait() 56 return self._exitCode
57
58 -class XServer(Subprocess):
59 - def __init__(self, server = "/usr/bin/Xorg", 60 xinitrc = "/etc/X11/xinit/Xclients", 61 resolution = "1024x768x16"):
62 """resolution is only used with Xvfb.""" 63 testBinary(server) 64 self.server = server 65 self._exitCode = None 66 self.xinit = "/usr/bin/xinit" 67 self.display = None 68 self.xinitrc = xinitrc 69 self.resolution = resolution
70 71 @staticmethod
72 - def findFreeDisplay():
73 tmp = os.listdir('/tmp') 74 pattern = re.compile('\.X([0-9]+)-lock') 75 usedDisplays = [] 76 for file in tmp: 77 match = re.match(pattern, file) 78 if match: usedDisplays.append(int(match.groups()[0])) 79 if not usedDisplays: return ':0' 80 usedDisplays.sort() 81 return ':' + str(usedDisplays[-1] + 1)
82 83 @property
84 - def cmdList(self):
85 self.display = self.findFreeDisplay() 86 cmd = [] 87 if self.xinit: 88 cmd.append(self.xinit) 89 if self.xinitrc: cmd.append(self.xinitrc) 90 cmd.append('--') 91 cmd.append(self.server) 92 cmd.append(self.display) 93 cmd.extend(['-ac', '-noreset']) 94 if self.server.endswith('Xvfb'): 95 cmd.extend(['-screen', '0', self.resolution]) 96 cmd.append('-shmem') 97 return cmd
98
99 - def start(self):
100 print ' '.join(self.cmdList) 101 self.popen = subprocess.Popen(self.cmdList) 102 return self.popen.pid
103
104 -class Script(Subprocess):
105 pass
106
107 -class Session(object):
108 109 cookieName = "DOGTAIL_SESSION_COOKIE" 110
111 - def __init__(self, sessionBinary, scriptCmdList = [], scriptDelay = 10, logout = True):
112 testBinary(sessionBinary) 113 self.sessionBinary = sessionBinary 114 self.script = Script(scriptCmdList) 115 self.scriptDelay = scriptDelay 116 self.logout = logout 117 self.xserver = XServer() 118 self._cookie = None 119 self._environment = None
120
121 - def start(self):
122 self.xinitrcFileObj = scratchFile('xinitrc') 123 self.xserver.xinitrc = self.xinitrcFileObj.name 124 self._buildXInitRC(self.xinitrcFileObj) 125 xServerPid = self.xserver.start() 126 time.sleep(self.scriptDelay) 127 self.script.environ = self.environment 128 scriptPid = self.script.start() 129 return (xServerPid, scriptPid)
130 131 @property
132 - def environment(self):
133 def isSessionProcess(fileName): 134 try: 135 if os.path.realpath(path + 'exe') != self.sessionBinary: 136 return False 137 except OSError: 138 return False 139 pid = fileName.split('/')[2] 140 if pid == 'self' or pid == str(os.getpid()): return False 141 return True
142 143 def getEnvDict(fileName): 144 try: envString = open(fileName, 'r').read() 145 except IOError: return {} 146 envItems = envString.split('\x00') 147 envDict = {} 148 for item in envItems: 149 if not '=' in item: continue 150 k, v = item.split('=', 1) 151 envDict[k] = v 152 return envDict
153 154 def isSessionEnv(envDict): 155 if not envDict: return False 156 if envDict.get(self.cookieName, 'notacookie') == self.cookie: 157 return True 158 return False 159 160 for path in glob.glob('/proc/*/'): 161 if not isSessionProcess(path): continue 162 envFile = path + 'environ' 163 envDict = getEnvDict(envFile) 164 if isSessionEnv(envDict): 165 #print path 166 #print envDict 167 self._environment = envDict 168 if not self._environment: 169 raise RuntimeError("Can't find our environment!") 170 return self._environment 171
172 - def wait(self):
173 self.script.wait() 174 return self.xserver.wait()
175
176 - def stop(self):
177 try: self.script.stop() 178 except OSError: pass 179 self.xserver.stop()
180
181 - def attemptLogout(self):
182 logoutScript = Script('dogtail-logout', 183 environ = self.environment) 184 logoutScript.start() 185 logoutScript.wait()
186 187 @property
188 - def cookie(self):
189 if not self._cookie: 190 self._cookie = "%X" % random.getrandbits(16) 191 return self._cookie
192
193 - def _buildXInitRC(self, fileObj):
194 if self.logout: 195 logoutString = "; dogtail-logout" 196 else: 197 logoutString = "" 198 lines = [ 199 "export %s=%s" % (self.cookieName, self.cookie), 200 "gconftool-2 --type bool --set /desktop/gnome/interface/accessibility true", 201 ". /etc/X11/xinit/xinitrc-common", 202 "export %s" % self.cookieName, 203 "exec -l $SHELL -c \"$CK_XINIT_SESSION $SSH_AGENT %s\"" % \ 204 self.sessionBinary, 205 ""] 206 207 fileObj.write('\n'.join(lines).strip()) 208 fileObj.flush()
209