summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/devshell.bbclass121
-rwxr-xr-xscripts/oepydevshell-internal.py92
2 files changed, 213 insertions, 0 deletions
diff --git a/meta/classes/devshell.bbclass b/meta/classes/devshell.bbclass
index 92edb9ef25..41164a3f33 100644
--- a/meta/classes/devshell.bbclass
+++ b/meta/classes/devshell.bbclass
@@ -31,3 +31,124 @@ python () {
31 d.setVarFlag("do_devshell", "manualfakeroot", "1") 31 d.setVarFlag("do_devshell", "manualfakeroot", "1")
32 d.delVarFlag("do_devshell", "fakeroot") 32 d.delVarFlag("do_devshell", "fakeroot")
33} 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"
diff --git a/scripts/oepydevshell-internal.py b/scripts/oepydevshell-internal.py
new file mode 100755
index 0000000000..f7b2e4e0bf
--- /dev/null
+++ b/scripts/oepydevshell-internal.py
@@ -0,0 +1,92 @@
1#!/usr/bin/env python
2
3import os
4import sys
5import time
6import select
7import fcntl
8import termios
9import readline
10import signal
11
12def nonblockingfd(fd):
13 fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
14
15def echonocbreak(fd):
16 old = termios.tcgetattr(fd)
17 old[3] = old[3] | termios.ECHO | termios.ICANON
18 termios.tcsetattr(fd, termios.TCSADRAIN, old)
19
20def cbreaknoecho(fd):
21 old = termios.tcgetattr(fd)
22 old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
23 termios.tcsetattr(fd, termios.TCSADRAIN, old)
24
25if len(sys.argv) != 3:
26 print("Incorrect parameters")
27 sys.exit(1)
28
29pty = open(sys.argv[1], "w+b", 0)
30parent = int(sys.argv[2])
31
32# Don't buffer output by line endings
33sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
34sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', 0)
35nonblockingfd(pty)
36nonblockingfd(sys.stdin)
37
38
39histfile = os.path.expanduser("~/.oedevpyshell-history")
40readline.parse_and_bind("tab: complete")
41try:
42 readline.read_history_file(histfile)
43except IOError:
44 pass
45
46try:
47
48 i = ""
49 o = ""
50 # Need cbreak/noecho whilst in select so we trigger on any keypress
51 cbreaknoecho(sys.stdin.fileno())
52 # Send our PID to the other end so they can kill us.
53 pty.write(str(os.getpid()) + "\n")
54 while True:
55 try:
56 writers = []
57 if i:
58 writers.append(sys.stdout)
59 (ready, _, _) = select.select([pty, sys.stdin], writers , [], 0)
60 try:
61 if pty in ready:
62 i = i + pty.read()
63 if i:
64 # Write a page at a time to avoid overflowing output
65 # d.keys() is a good way to do that
66 sys.stdout.write(i[:4096])
67 i = i[4096:]
68 if sys.stdin in ready:
69 echonocbreak(sys.stdin.fileno())
70 o = raw_input()
71 cbreaknoecho(sys.stdin.fileno())
72 pty.write(o + "\n")
73 except (IOError, OSError) as e:
74 if e.errno == 11:
75 continue
76 if e.errno == 5:
77 sys.exit(0)
78 raise
79 except EOFError:
80 sys.exit(0)
81 except KeyboardInterrupt:
82 os.kill(parent, signal.SIGINT)
83
84except SystemExit:
85 pass
86except Exception as e:
87 import traceback
88 print("Exception in oepydehshell-internal: " + str(e))
89 traceback.print_exc()
90 time.sleep(5)
91finally:
92 readline.write_history_file(histfile)