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