#!/usr/bin/env python
#
#  Restart the firewall, stop it if it looks like we're locked out.
#
#  License: GPL v2

fwRestartCmd = '/sbin/service iptables start'
fwClearCmd = '/sbin/service iptables stop'

import sys, select, time, tty, signal, os, copy
from termios import *


########################################
G_oldMode = None
def setraw(fd, when = None):
	global G_oldMode
	if not when: when = TCSAFLUSH
	mode = tcgetattr(fd)
	if not G_oldMode: G_oldMode = copy.copy(mode)
	mode[0] = mode[0] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
	mode[1] = mode[1] & ~(OPOST)
	mode[2] = mode[2] & ~(CSIZE | PARENB)
	mode[2] = mode[2] | CS8
	mode[3] = mode[3] & ~(ECHO | ICANON | IEXTEN | ISIG)
	mode[6][VMIN] = 1
	mode[6][VTIME] = 0
	tcsetattr(fd, when, mode)


#############################
def setorig(fd, when = None):
	global G_oldMode
	if not when: when = TCSAFLUSH
	mode = G_oldMode
	tcsetattr(fd, when, G_oldMode)


################################
class alarmException(Exception):
	pass


#############################
def alarmHandler(sig, frame):
	raise alarmException, 'Alarm triggered'


############################
def intrHandler(sig, frame):
	setorig(0)


##########################
def readResp(fp, timeout):
	signal.signal(signal.SIGALRM, alarmHandler)
	signal.alarm(timeout)
	s = ''
	while 1:
		try: s = s + sys.stdin.read(1)
		except alarmException: break
		if s == '\033[0n': break
	signal.alarm(0)
	signal.signal(signal.SIGALRM, signal.SIG_DFL)
	return(s)


#########################################
signal.signal(signal.SIGINT, intrHandler)
setraw(0)
tty = open('/dev/tty', 'wb+')

#  try pinging terminal
tty.write('\033[5n'); tty.flush()
s = readResp(sys.stdin, 3)
if s != '\033[0n':
	setorig(0)
	print 'Unable to ping terminal, aborting!'
	sys.exit(1)

#  restart firewall
os.system(fwRestartCmd)

#  try to contact terminal
tty.write('\033[5n'); tty.flush()
s = readResp(sys.stdin, 10)
cleared = 0
if s != '\033[0n':
	os.system(fwClearCmd)
	cleared = 1

	#  read response now that the firewall is off
	s = readResp(sys.stdin, 60)

#  return terminal to normal state
setorig(0)

#  display failure message
if cleared:
	print '\007WARNING: Firewall seemed to block this session.'
	print 'WARNING: Firewall has been removed, investigate and try again.'
	sys.exit(1)

sys.exit(0)
