blob: 62dc958d9a4a50bac7e55be0b61d5d4b0950c8a3 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001inherit terminal
2
3DEVSHELL = "${SHELL}"
4
5python do_devshell () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05006 if d.getVarFlag("do_devshell", "manualfakeroot"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05007 d.prependVar("DEVSHELL", "pseudo ")
Brad Bishop6e60e8b2018-02-01 10:27:11 -05008 fakeenv = d.getVar("FAKEROOTENV").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05009 for f in fakeenv:
10 k = f.split("=")
Brad Bishopd7bf8c12018-02-25 22:55:05 -050011 d.setVar(k[0], k[1])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012 d.appendVar("OE_TERMINAL_EXPORTS", " " + k[0])
13 d.delVarFlag("do_devshell", "fakeroot")
14
Brad Bishop6e60e8b2018-02-01 10:27:11 -050015 oe_terminal(d.getVar('DEVSHELL'), 'OpenEmbedded Developer Shell', d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050016}
17
Brad Bishopd7bf8c12018-02-25 22:55:05 -050018addtask devshell after do_patch do_prepare_recipe_sysroot
Patrick Williamsc124f4f2015-09-15 14:41:29 -050019
20# The directory that the terminal starts in
21DEVSHELL_STARTDIR ?= "${S}"
22do_devshell[dirs] = "${DEVSHELL_STARTDIR}"
23do_devshell[nostamp] = "1"
24
25# devshell and fakeroot/pseudo need careful handling since only the final
26# command should run under fakeroot emulation, any X connection should
27# be done as the normal user. We therfore carefully construct the envionment
28# manually
29python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -050030 if d.getVarFlag("do_devshell", "fakeroot"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031 # We need to signal our code that we want fakeroot however we
32 # can't manipulate the environment and variables here yet (see YOCTO #4795)
33 d.setVarFlag("do_devshell", "manualfakeroot", "1")
34 d.delVarFlag("do_devshell", "fakeroot")
35}
36
Andrew Geisslereff27472021-10-29 15:35:00 -050037def pydevshell(d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050038
39 import code
40 import select
41 import signal
42 import termios
43
44 m, s = os.openpty()
45 sname = os.ttyname(s)
46
47 def noechoicanon(fd):
48 old = termios.tcgetattr(fd)
49 old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
50 # &~ termios.ISIG
51 termios.tcsetattr(fd, termios.TCSADRAIN, old)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050052
Patrick Williamsc124f4f2015-09-15 14:41:29 -050053 # No echo or buffering over the pty
54 noechoicanon(s)
55
56 pid = os.fork()
57 if pid:
58 os.close(m)
59 oe_terminal("oepydevshell-internal.py %s %d" % (sname, pid), 'OpenEmbedded Developer PyShell', d)
60 os._exit(0)
61 else:
62 os.close(s)
63
64 os.dup2(m, sys.stdin.fileno())
65 os.dup2(m, sys.stdout.fileno())
66 os.dup2(m, sys.stderr.fileno())
67
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068 bb.utils.nonblockingfd(sys.stdout)
69 bb.utils.nonblockingfd(sys.stderr)
70 bb.utils.nonblockingfd(sys.stdin)
71
72 _context = {
73 "os": os,
74 "bb": bb,
75 "time": time,
76 "d": d,
77 }
78
79 ps1 = "pydevshell> "
80 ps2 = "... "
81 buf = []
82 more = False
83
84 i = code.InteractiveInterpreter(locals=_context)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050085 print("OE PyShell (PN = %s)\n" % d.getVar("PN"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086
87 def prompt(more):
88 if more:
89 prompt = ps2
90 else:
91 prompt = ps1
92 sys.stdout.write(prompt)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060093 sys.stdout.flush()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094
95 # Restore Ctrl+C since bitbake masks this
96 def signal_handler(signal, frame):
97 raise KeyboardInterrupt
98 signal.signal(signal.SIGINT, signal_handler)
99
100 child = None
101
102 prompt(more)
103 while True:
104 try:
105 try:
106 (r, _, _) = select.select([sys.stdin], [], [], 1)
107 if not r:
108 continue
109 line = sys.stdin.readline().strip()
110 if not line:
111 prompt(more)
112 continue
113 except EOFError as e:
114 sys.stdout.write("\n")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600115 sys.stdout.flush()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116 except (OSError, IOError) as e:
117 if e.errno == 11:
118 continue
119 if e.errno == 5:
120 return
121 raise
122 else:
123 if not child:
124 child = int(line)
125 continue
126 buf.append(line)
127 source = "\n".join(buf)
128 more = i.runsource(source, "<pyshell>")
129 if not more:
130 buf = []
Andrew Geissler95ac1b82021-03-31 14:34:31 -0500131 sys.stderr.flush()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132 prompt(more)
133 except KeyboardInterrupt:
134 i.write("\nKeyboardInterrupt\n")
135 buf = []
136 more = False
137 prompt(more)
138 except SystemExit:
139 # Easiest way to ensure everything exits
140 os.kill(child, signal.SIGTERM)
141 break
142
Andrew Geisslereff27472021-10-29 15:35:00 -0500143python do_pydevshell() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 import signal
145
146 try:
Andrew Geisslereff27472021-10-29 15:35:00 -0500147 pydevshell(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500148 except SystemExit:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500149 # Stop the SIGTERM above causing an error exit code
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500150 return
151 finally:
152 return
153}
Andrew Geisslereff27472021-10-29 15:35:00 -0500154addtask pydevshell after do_patch
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155
Andrew Geisslereff27472021-10-29 15:35:00 -0500156do_pydevshell[nostamp] = "1"