#!/usr/bin/python

import os
import sys
import subprocess
import time
import signal
import socket
import struct
import fcntl

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.ip = get_ip('eth0')

        if self.use_xfs:
            xfs_server = get_config('XFS_SERVER') or self.server
            self.fontpath = "tcp/%s:7100" % xfs_server

    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'] + 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
            
            time.sleep(5)
            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['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)]

            ssh_remote_command = ['env', 
                                  'LTSP_CLIENT="%s"' % (socket.gethostname()),
				  'esddsp', '-m','--server=%s:16001' % (self.ip),
                                  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 <vt[1-N]> <:[0-N]>\n')
    sys.exit(1)

vt, display = sys.argv[1:]
ldm = LDM(vt, display)
ldm.run()
