#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  bt_shell.py
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#  Works with BlueTerm on Android
#    https://play.google.com/store/apps/details?id=es.pymasde.blueterm&hl=en
#
#  Author: Spencer McIntyre (@zeroSteiner)

import os
import pty
import uuid

import bluetooth

def child_process(sock):
	os.dup2(sock.fileno(), 0)
	os.dup2(sock.fileno(), 1)
	os.dup2(sock.fileno(), 2)
	os.putenv('HISTFILE', os.devnull)
	pty.spawn(os.environ.get('SHELL', '/bin/sh'))

	print('Disconnecting...')
	sock.close()
	os._exit(0)

def main():
	server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
	server_sock.bind(('', bluetooth.PORT_ANY))
	server_sock.listen(1)

	port = server_sock.getsockname()[1]
	random_uuid = str(uuid.uuid4())

	bluetooth.advertise_service(server_sock,
		'ShellServer',
		service_id=random_uuid,
		service_classes=[random_uuid, bluetooth.SERIAL_PORT_CLASS],
		profiles=[bluetooth.SERIAL_PORT_PROFILE]
	)

	print("Waiting for connection on RFCOMM channel {0}".format(port))

	while True:
		try:
			client_sock, (client_addr, client_ch) = server_sock.accept()
		except KeyboardInterrupt:
			break
		print("Accepted connection from {0}".format(client_addr))
		pid = os.fork()
		if pid:
			print("Forked shell process {0}".format(pid))
		else:
			child_process(client_sock)
		client_sock.close()

	print('Shutting down the server socket...')
	server_sock.close()

if __name__ == '__main__':
	main()