#!/usr/bin/python import os import sys import subprocess import time import signal import socket import struct import fcntl import tempfile def get_config(name): return os.environ.get(name) def get_config_bool(name): val = os.environ.get(name) return (val and val.lower() == 'y') def get_ip(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # SIOCGIFADDR struct.pack('256s', ifname[:15]) )[20:24]) class LDM: def __init__(self, vt, display): self.vt = vt self.display = display self.server = get_config('SERVER') self.use_xfs = get_config_bool('USE_XFS') self.remotecmd = get_config('LDM_REMOTECMD') or '/etc/X11/Xsession' self.use_sound = get_config_bool('SOUND') if self.use_sound: self.ip = get_ip('eth0') self.sound_daemon = get_config('SOUND_DAEMON') or 'esd' if self.use_xfs: xfs_server = get_config('XFS_SERVER') or self.server self.fontpath = "tcp/%s:7100" % xfs_server # Save xauth info some writable tmpfs file. self.authfile = tempfile.mktemp() def run(self): null = open('/dev/null', 'w') logfile = open('/var/log/ldm.log', 'a') os.dup2(null.fileno(), sys.stdin.fileno()) os.dup2(logfile.fileno(), sys.stdout.fileno()) os.dup2(logfile.fileno(), sys.stderr.fileno()) while True: server_opts = ['-br', '-ac', '-noreset'] if self.use_xfs: server_opts += ['-fp', self.fontpath] server_command = ['X', '-auth', self.authfile] + server_opts + [self.vt, self.display] server = subprocess.Popen(server_command, stdout=sys.stdout, stderr=sys.stderr) env = os.environ.copy() env['DISPLAY'] = self.display env['XAUTHORITY'] = self.authfile time.sleep(5) # Generate an X authority key in ~/.Xauthority xauth_command = ['xauth', '-f', self.authfile, 'generate', self.display] xauth = subprocess.Popen(xauth_command, stdout=sys.stdout, stderr=sys.stderr, env=env) os.waitpid(xauth.pid, 0) greeter = subprocess.Popen(['/usr/lib/ltsp/greeters/gtk'], stdout=subprocess.PIPE, stderr=sys.stderr, env=env) greeter_output = greeter.stdout.readlines() if len(greeter_output) == 2: username = greeter_output[0][:-1] password = greeter_output[1][:-1] self.spawn_session(username, password, self.remotecmd) else: print "Didn't get the right output from the greeter" os.kill(server.pid, signal.SIGTERM) os.waitpid(server.pid, 0) def spawn_session(self, username, password, session_manager): pipe_read, pipe_write = os.pipe() pid = os.fork() if pid == 0: os.close(pipe_write) sys.stdin.close() os.setsid() os.environ['DISPLAY'] = self.display os.environ['XAUTHORITY'] = self.authfile os.environ['LDM_ASKPASS_FD'] = str(pipe_read) os.environ['SSH_ASKPASS'] = '/usr/lib/ltsp/ldm-askpass' ssh_opts = ['-v', '-X', '-c', 'blowfish-cbc,aes128-cbc,3des-cbc'] ssh_auth = ['%s@%s' % (username,self.server)] if self.use_sound: if self.sound_daemon == 'esd': print "info: Enabling esd sound support." # Could start using esddsp, but it is not enabled # because it gave problems when using firefox. # esddsp', '-m','--server=%s:16001' % (self.ip) espeakerport = 16001 sound_cmd = ['ESPEAKER=%s:%d' % (self.ip, espeakerport)] elif self.sound_daemon == 'nasd': print "info: Enabling nasd sound support." # Could use the audiooss package to set LD_PRELOAD. # Not enabled by default to avoid problems with # firefox. sound_cmd = ['AUDIOSERVER=%s:0' % (self.ip)] else: print "error: Unsupported sound daemon: '%s'" % \ (self.sound_daemon) sound_cmd = [] else: print "info: Not enabling sound support." sound_cmd = [] ssh_remote_command = ['env', 'LTSP_CLIENT="%s"' % (socket.gethostname()), ] + sound_cmd + [ session_manager, ';', 'kill -1 $PPID'] if 'NETWORK_COMPRESSION' in os.environ: ssh_opts.append('-C') command = ['ssh'] + ssh_opts + ssh_auth + ssh_remote_command print "ssh command line:", command sys.stdout.flush() os.execvp('ssh', command) sys.exit(1) os.close(pipe_read) os.write(pipe_write,password) os.close(pipe_write) os.waitpid(pid, 0) if len(sys.argv) < 3: sys.stderr.write('Usage: ldm <:[0-N]>\n') sys.exit(1) vt, display = sys.argv[1:] ldm = LDM(vt, display) ldm.run()