xref: /OK3568_Linux_fs/yocto/poky/meta/classes/devshell.bbclass (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1inherit terminal
2
3DEVSHELL = "${SHELL}"
4
5python do_devshell () {
6    if d.getVarFlag("do_devshell", "manualfakeroot"):
7       d.prependVar("DEVSHELL", "pseudo ")
8       fakeenv = d.getVar("FAKEROOTENV").split()
9       for f in fakeenv:
10            k = f.split("=")
11            d.setVar(k[0], k[1])
12            d.appendVar("OE_TERMINAL_EXPORTS", " " + k[0])
13       d.delVarFlag("do_devshell", "fakeroot")
14
15    oe_terminal(d.getVar('DEVSHELL'), 'OpenEmbedded Developer Shell', d)
16}
17
18addtask devshell after do_patch do_prepare_recipe_sysroot
19
20# The directory that the terminal starts in
21DEVSHELL_STARTDIR ?= "${S}"
22do_devshell[dirs] = "${DEVSHELL_STARTDIR}"
23do_devshell[nostamp] = "1"
24do_devshell[network] = "1"
25
26# devshell and fakeroot/pseudo need careful handling since only the final
27# command should run under fakeroot emulation, any X connection should
28# be done as the normal user. We therfore carefully construct the envionment
29# manually
30python () {
31    if d.getVarFlag("do_devshell", "fakeroot"):
32       # We need to signal our code that we want fakeroot however we
33       # can't manipulate the environment and variables here yet (see YOCTO #4795)
34       d.setVarFlag("do_devshell", "manualfakeroot", "1")
35       d.delVarFlag("do_devshell", "fakeroot")
36}
37
38def pydevshell(d):
39
40    import code
41    import select
42    import signal
43    import termios
44
45    m, s = os.openpty()
46    sname = os.ttyname(s)
47
48    def noechoicanon(fd):
49        old = termios.tcgetattr(fd)
50        old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
51        # &~ termios.ISIG
52        termios.tcsetattr(fd, termios.TCSADRAIN, old)
53
54    # No echo or buffering over the pty
55    noechoicanon(s)
56
57    pid = os.fork()
58    if pid:
59        os.close(m)
60        oe_terminal("oepydevshell-internal.py %s %d" % (sname, pid), 'OpenEmbedded Developer PyShell', d)
61        os._exit(0)
62    else:
63        os.close(s)
64
65        os.dup2(m, sys.stdin.fileno())
66        os.dup2(m, sys.stdout.fileno())
67        os.dup2(m, sys.stderr.fileno())
68
69        bb.utils.nonblockingfd(sys.stdout)
70        bb.utils.nonblockingfd(sys.stderr)
71        bb.utils.nonblockingfd(sys.stdin)
72
73        _context = {
74            "os": os,
75            "bb": bb,
76            "time": time,
77            "d": d,
78        }
79
80        ps1 = "pydevshell> "
81        ps2 = "... "
82        buf = []
83        more = False
84
85        i = code.InteractiveInterpreter(locals=_context)
86        print("OE PyShell (PN = %s)\n" % d.getVar("PN"))
87
88        def prompt(more):
89            if more:
90                prompt = ps2
91            else:
92                prompt = ps1
93            sys.stdout.write(prompt)
94            sys.stdout.flush()
95
96        # Restore Ctrl+C since bitbake masks this
97        def signal_handler(signal, frame):
98            raise KeyboardInterrupt
99        signal.signal(signal.SIGINT, signal_handler)
100
101        child = None
102
103        prompt(more)
104        while True:
105            try:
106                try:
107                    (r, _, _) = select.select([sys.stdin], [], [], 1)
108                    if not r:
109                        continue
110                    line = sys.stdin.readline().strip()
111                    if not line:
112                        prompt(more)
113                        continue
114                except EOFError as e:
115                    sys.stdout.write("\n")
116                    sys.stdout.flush()
117                except (OSError, IOError) as e:
118                    if e.errno == 11:
119                        continue
120                    if e.errno == 5:
121                        return
122                    raise
123                else:
124                    if not child:
125                        child = int(line)
126                        continue
127                    buf.append(line)
128                    source = "\n".join(buf)
129                    more = i.runsource(source, "<pyshell>")
130                    if not more:
131                        buf = []
132                    sys.stderr.flush()
133                    prompt(more)
134            except KeyboardInterrupt:
135                i.write("\nKeyboardInterrupt\n")
136                buf = []
137                more = False
138                prompt(more)
139            except SystemExit:
140                # Easiest way to ensure everything exits
141                os.kill(child, signal.SIGTERM)
142                break
143
144python do_pydevshell() {
145    import signal
146
147    try:
148        pydevshell(d)
149    except SystemExit:
150        # Stop the SIGTERM above causing an error exit code
151        return
152    finally:
153        return
154}
155addtask pydevshell after do_patch
156
157do_pydevshell[nostamp] = "1"
158do_pydevshell[network] = "1"
159