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