blob: e3c35bbe2cd2a6040975def2fd47dcb543500d9d [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Brad Bishopc342db32019-05-15 21:57:59 -04002#
3# SPDX-License-Identifier: GPL-2.0-only
4#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05005
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050028if 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)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050038
39pty = open(sys.argv[1], "w+b", 0)
40parent = int(sys.argv[2])
41
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042nonblockingfd(pty)
43nonblockingfd(sys.stdin)
44
45
Andrew Geisslereff27472021-10-29 15:35:00 -050046histfile = os.path.expanduser("~/.oepydevshell-history")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047readline.parse_and_bind("tab: complete")
48try:
49 readline.read_history_file(histfile)
50except IOError:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050051 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052
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.
Patrick Williamsc0f7c042017-02-23 20:41:17 -060060 pty.write(str(os.getpid()).encode('utf-8') + b"\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061 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:
Brad Bishop19323692019-04-05 15:28:33 -040069 readdata = pty.read()
70 if readdata:
71 i = i + readdata.decode('utf-8')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050072 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])
Patrick Williamsc0f7c042017-02-23 20:41:17 -060076 sys.stdout.flush()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077 i = i[4096:]
78 if sys.stdin in ready:
79 echonocbreak(sys.stdin.fileno())
Patrick Williamsc0f7c042017-02-23 20:41:17 -060080 o = input().encode('utf-8')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081 cbreaknoecho(sys.stdin.fileno())
Patrick Williamsc0f7c042017-02-23 20:41:17 -060082 pty.write(o + b"\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083 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)