#!/usr/bin/env python
# -*- coding: utf-8 -*-

from optparse import OptionParser
parser = OptionParser(usage='%prog [options]')
parser.add_option('-c',
	action='store_true', dest='shell',
	help='rsync-only shell mode')
optz, argz = parser.parse_args()


import os, sys

if optz.shell:
	import pwd, grp, re
	cmd = os.getenv('SSH_ORIGINAL_COMMAND')
	if not cmd: parser.error('No SSH_ORIGINAL_COMMAND in ENV')
	if not re.match(
			r'^(ionice -c\d( -n\d)? )?rsync --server', cmd ):
		parser.error('Disallowed command: {0}'.format(cmd))
	try: cmd, argz = cmd.split(' ', 1)
	except ValueError: argz = ''
	os.execlp(cmd, os.path.basename(cmd), *argz.split())


from string import whitespace as spaces
from fgc import sh, exe
import signal, socket

spool = '/var/spool/backup'
remote = 'cloner@alpharius'
remote_ip = socket.getaddrinfo(
	remote.split('@')[-1], None )[0][4][0]
port = 23
key = 'key'
key_pub = '{0}.pub'.format(key)


if not os.path.isdir(spool): sh.mkdir(spool)
os.chdir(spool)
lock = sh.flock('state.lock', make=True).acquire(60)

sh.rm(key, onerror=False)
sh.rm(key_pub, onerror=False)

def unjam(sig, frm):
	raise RuntimeError, 'no data from ssh-keygen'
signal.signal(signal.SIGALRM, unjam)

os.mkfifo(key)
keygen = exe.proc( 'ssh-keygen', '-q',
	'-t', 'rsa', '-b', '2048', '-N', '', '-f', key )

signal.alarm(5)
key_sub = open(key).read()
sh.rm(key, onerror=False)
if keygen.wait(): raise RuntimeError, 'ssh-keygen has failed'
signal.alarm(0)

keygen = open(key_pub, 'r').read().strip(spaces)
open(key_pub, 'w').write(
	'from="{0}" {1}\n'.format(remote_ip, keygen) )
sh.gc(key_pub)


sshd = exe.proc( '/usr/sbin/sshd', '-6', '-de', '-p{0}'.format(port),
	'-oChallengeResponseAuthentication=no', # no password prompt
	'-oAllowAgentForwarding=no', # no need for this
	'-oAllowTcpForwarding=no', # no port-forwarding
	'-oPermitTunnel=no', # no tunneling
	'-oCompression=no', # minor speedup, since it's handled by rsync
	'-oForceCommand=/usr/bin/ppy {0} -c'\
		.format(os.path.realpath(__file__)), # enforce this script checks
	'-oAuthorizedKeysFile={0}'.format( # realpath _only_!
		os.path.realpath(key_pub) ), silent=True )

ssh = exe.proc( 'ssh', remote,
	'{0}:{1}'.format(os.uname()[1], port), stdin=exe.PIPE )
ssh.stdin.write(key_sub)
ssh.stdin.write('\n\n\n')
ssh.stdin.write(open('/etc/bak_exclude').read())
ssh.stdin.close()


if ssh.wait(): raise RuntimeError, 'Remote call failed'
lock.release()

