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