summaryrefslogtreecommitdiffstats
path: root/meta/classes/devshell.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes/devshell.bbclass')
-rw-r--r--meta/classes/devshell.bbclass154
1 files changed, 154 insertions, 0 deletions
diff --git a/meta/classes/devshell.bbclass b/meta/classes/devshell.bbclass
new file mode 100644
index 0000000000..41164a3f33
--- /dev/null
+++ b/meta/classes/devshell.bbclass
@@ -0,0 +1,154 @@
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", True).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', True), 'OpenEmbedded Developer Shell', d)
16}
17
18addtask devshell after do_patch
19
20do_devshell[dirs] = "${S}"
21do_devshell[nostamp] = "1"
22
23# devshell and fakeroot/pseudo need careful handling since only the final
24# command should run under fakeroot emulation, any X connection should
25# be done as the normal user. We therfore carefully construct the envionment
26# manually
27python () {
28 if d.getVarFlag("do_devshell", "fakeroot"):
29 # We need to signal our code that we want fakeroot however we
30 # can't manipulate the environment and variables here yet (see YOCTO #4795)
31 d.setVarFlag("do_devshell", "manualfakeroot", "1")
32 d.delVarFlag("do_devshell", "fakeroot")
33}
34
35def devpyshell(d):
36
37 import code
38 import select
39 import signal
40 import termios
41
42 m, s = os.openpty()
43 sname = os.ttyname(s)
44
45 def noechoicanon(fd):
46 old = termios.tcgetattr(fd)
47 old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
48 # &~ termios.ISIG
49 termios.tcsetattr(fd, termios.TCSADRAIN, old)
50
51 # No echo or buffering over the pty
52 noechoicanon(s)
53
54 pid = os.fork()
55 if pid:
56 os.close(m)
57 oe_terminal("oepydevshell-internal.py %s %d" % (sname, pid), 'OpenEmbedded Developer PyShell', d)
58 os._exit(0)
59 else:
60 os.close(s)
61
62 os.dup2(m, sys.stdin.fileno())
63 os.dup2(m, sys.stdout.fileno())
64 os.dup2(m, sys.stderr.fileno())
65
66 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
67 sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', 0)
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", True))
87
88 def prompt(more):
89 if more:
90 prompt = ps2
91 else:
92 prompt = ps1
93 sys.stdout.write(prompt)
94
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")
115 except (OSError, IOError) as e:
116 if e.errno == 11:
117 continue
118 if e.errno == 5:
119 return
120 raise
121 else:
122 if not child:
123 child = int(line)
124 continue
125 buf.append(line)
126 source = "\n".join(buf)
127 more = i.runsource(source, "<pyshell>")
128 if not more:
129 buf = []
130 prompt(more)
131 except KeyboardInterrupt:
132 i.write("\nKeyboardInterrupt\n")
133 buf = []
134 more = False
135 prompt(more)
136 except SystemExit:
137 # Easiest way to ensure everything exits
138 os.kill(child, signal.SIGTERM)
139 break
140
141python do_devpyshell() {
142 import signal
143
144 try:
145 devpyshell(d)
146 except SystemExit:
147 # Stop the SIGTERM above causing an error exit code
148 return
149 finally:
150 return
151}
152addtask devpyshell after do_patch
153
154do_devpyshell[nostamp] = "1"