1#!/usr/bin/env python3 2# 3# SPDX-License-Identifier: GPL-2.0-only 4# 5 6import os 7import sys 8import time 9import select 10import fcntl 11import termios 12import readline 13import signal 14 15def nonblockingfd(fd): 16 fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) 17 18def echonocbreak(fd): 19 old = termios.tcgetattr(fd) 20 old[3] = old[3] | termios.ECHO | termios.ICANON 21 termios.tcsetattr(fd, termios.TCSADRAIN, old) 22 23def cbreaknoecho(fd): 24 old = termios.tcgetattr(fd) 25 old[3] = old[3] &~ termios.ECHO &~ termios.ICANON 26 termios.tcsetattr(fd, termios.TCSADRAIN, old) 27 28if len(sys.argv) != 3 or sys.argv[1] in ('-h', '--help'): 29 print('oepydevshell-internal.py: error: the following arguments are required: pty, pid\n' 30 'Usage: oepydevshell-internal.py pty pid\n\n' 31 'OpenEmbedded oepydevshell-internal.py - internal script called from meta/classes/devshell.bbclass\n\n' 32 'arguments:\n' 33 ' pty pty device name\n' 34 ' pid parent process id\n\n' 35 'options:\n' 36 ' -h, --help show this help message and exit\n') 37 sys.exit(2) 38 39pty = open(sys.argv[1], "w+b", 0) 40parent = int(sys.argv[2]) 41 42nonblockingfd(pty) 43nonblockingfd(sys.stdin) 44 45 46histfile = os.path.expanduser("~/.oepydevshell-history") 47readline.parse_and_bind("tab: complete") 48try: 49 readline.read_history_file(histfile) 50except IOError: 51 pass 52 53try: 54 55 i = "" 56 o = "" 57 # Need cbreak/noecho whilst in select so we trigger on any keypress 58 cbreaknoecho(sys.stdin.fileno()) 59 # Send our PID to the other end so they can kill us. 60 pty.write(str(os.getpid()).encode('utf-8') + b"\n") 61 while True: 62 try: 63 writers = [] 64 if i: 65 writers.append(sys.stdout) 66 (ready, _, _) = select.select([pty, sys.stdin], writers , [], 0) 67 try: 68 if pty in ready: 69 readdata = pty.read() 70 if readdata: 71 i = i + readdata.decode('utf-8') 72 if i: 73 # Write a page at a time to avoid overflowing output 74 # d.keys() is a good way to do that 75 sys.stdout.write(i[:4096]) 76 sys.stdout.flush() 77 i = i[4096:] 78 if sys.stdin in ready: 79 echonocbreak(sys.stdin.fileno()) 80 o = input().encode('utf-8') 81 cbreaknoecho(sys.stdin.fileno()) 82 pty.write(o + b"\n") 83 except (IOError, OSError) as e: 84 if e.errno == 11: 85 continue 86 if e.errno == 5: 87 sys.exit(0) 88 raise 89 except EOFError: 90 sys.exit(0) 91 except KeyboardInterrupt: 92 os.kill(parent, signal.SIGINT) 93 94except SystemExit: 95 pass 96except Exception as e: 97 import traceback 98 print("Exception in oepydehshell-internal: " + str(e)) 99 traceback.print_exc() 100 time.sleep(5) 101finally: 102 readline.write_history_file(histfile) 103