| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 2 |  | 
|  | 3 | import os | 
|  | 4 | import sys | 
|  | 5 | import time | 
|  | 6 | import select | 
|  | 7 | import fcntl | 
|  | 8 | import termios | 
|  | 9 | import readline | 
|  | 10 | import signal | 
|  | 11 |  | 
|  | 12 | def nonblockingfd(fd): | 
|  | 13 | fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) | 
|  | 14 |  | 
|  | 15 | def echonocbreak(fd): | 
|  | 16 | old = termios.tcgetattr(fd) | 
|  | 17 | old[3] = old[3] | termios.ECHO | termios.ICANON | 
|  | 18 | termios.tcsetattr(fd, termios.TCSADRAIN, old) | 
|  | 19 |  | 
|  | 20 | def cbreaknoecho(fd): | 
|  | 21 | old = termios.tcgetattr(fd) | 
|  | 22 | old[3] = old[3] &~ termios.ECHO &~ termios.ICANON | 
|  | 23 | termios.tcsetattr(fd, termios.TCSADRAIN, old) | 
|  | 24 |  | 
|  | 25 | if len(sys.argv) != 3: | 
|  | 26 | print("Incorrect parameters") | 
|  | 27 | sys.exit(1) | 
|  | 28 |  | 
|  | 29 | pty = open(sys.argv[1], "w+b", 0) | 
|  | 30 | parent = int(sys.argv[2]) | 
|  | 31 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 32 | nonblockingfd(pty) | 
|  | 33 | nonblockingfd(sys.stdin) | 
|  | 34 |  | 
|  | 35 |  | 
|  | 36 | histfile = os.path.expanduser("~/.oedevpyshell-history") | 
|  | 37 | readline.parse_and_bind("tab: complete") | 
|  | 38 | try: | 
|  | 39 | readline.read_history_file(histfile) | 
|  | 40 | except IOError: | 
|  | 41 | pass | 
|  | 42 |  | 
|  | 43 | try: | 
|  | 44 |  | 
|  | 45 | i = "" | 
|  | 46 | o = "" | 
|  | 47 | # Need cbreak/noecho whilst in select so we trigger on any keypress | 
|  | 48 | cbreaknoecho(sys.stdin.fileno()) | 
|  | 49 | # Send our PID to the other end so they can kill us. | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 50 | pty.write(str(os.getpid()).encode('utf-8') + b"\n") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 51 | while True: | 
|  | 52 | try: | 
|  | 53 | writers = [] | 
|  | 54 | if i: | 
|  | 55 | writers.append(sys.stdout) | 
|  | 56 | (ready, _, _) = select.select([pty, sys.stdin], writers , [], 0) | 
|  | 57 | try: | 
|  | 58 | if pty in ready: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 59 | i = i + pty.read().decode('utf-8') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 60 | if i: | 
|  | 61 | # Write a page at a time to avoid overflowing output | 
|  | 62 | # d.keys() is a good way to do that | 
|  | 63 | sys.stdout.write(i[:4096]) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 64 | sys.stdout.flush() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 65 | i = i[4096:] | 
|  | 66 | if sys.stdin in ready: | 
|  | 67 | echonocbreak(sys.stdin.fileno()) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 68 | o = input().encode('utf-8') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 69 | cbreaknoecho(sys.stdin.fileno()) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 70 | pty.write(o + b"\n") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 71 | except (IOError, OSError) as e: | 
|  | 72 | if e.errno == 11: | 
|  | 73 | continue | 
|  | 74 | if e.errno == 5: | 
|  | 75 | sys.exit(0) | 
|  | 76 | raise | 
|  | 77 | except EOFError: | 
|  | 78 | sys.exit(0) | 
|  | 79 | except KeyboardInterrupt: | 
|  | 80 | os.kill(parent, signal.SIGINT) | 
|  | 81 |  | 
|  | 82 | except SystemExit: | 
|  | 83 | pass | 
|  | 84 | except Exception as e: | 
|  | 85 | import traceback | 
|  | 86 | print("Exception in oepydehshell-internal: " + str(e)) | 
|  | 87 | traceback.print_exc() | 
|  | 88 | time.sleep(5) | 
|  | 89 | finally: | 
|  | 90 | readline.write_history_file(histfile) |