Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 630112e

Browse files
committed
demonstrate shell in a Tk window
1 parent b8fe9b3 commit 630112e

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

Demo/tkinter/guido/ShellWindow.py

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import os
2+
import sys
3+
import string
4+
from Tkinter import *
5+
from ScrolledText import ScrolledText
6+
from Dialog import Dialog
7+
import signal
8+
9+
TK_READABLE = 1
10+
TK_WRITABLE = 2
11+
TK_EXCEPTION = 4
12+
13+
BUFSIZE = 512
14+
15+
class ShellWindow(ScrolledText):
16+
17+
def __init__(self, master = None, cnf = {}):
18+
try:
19+
shell = cnf['shell']
20+
del cnf['shell']
21+
except KeyError:
22+
try:
23+
shell = os.environ['SHELL']
24+
except KeyError:
25+
shell = '/bin/sh'
26+
shell = shell + ' -i'
27+
args = string.split(shell)
28+
shell = args[0]
29+
30+
ScrolledText.__init__(self, master, cnf)
31+
self.pos = '1.0'
32+
self.bind('<Return>', self.inputhandler)
33+
self.bind('<Control-c>', self.sigint)
34+
self.bind('<Control-t>', self.sigterm)
35+
self.bind('<Control-k>', self.sigkill)
36+
self.bind('<Control-d>', self.sendeof)
37+
38+
self.pid, self.fromchild, self.tochild = spawn(shell, args)
39+
self.tk.createfilehandler(self.fromchild, TK_READABLE,
40+
self.outputhandler)
41+
42+
def outputhandler(self, file, mask):
43+
data = os.read(file, BUFSIZE)
44+
if not data:
45+
self.tk.deletefilehandler(file)
46+
pid, sts = os.waitpid(self.pid, 0)
47+
print 'pid', pid, 'status', sts
48+
self.pid = None
49+
detail = sts>>8
50+
cause = sts & 0xff
51+
if cause == 0:
52+
msg = "exit status %d" % detail
53+
else:
54+
msg = "killed by signal %d" % (cause & 0x7f)
55+
if cause & 0x80:
56+
msg = msg + " -- core dumped"
57+
Dialog(self.master, {
58+
'text': msg,
59+
'title': "Exit status",
60+
'bitmap': 'warning',
61+
'default': 0,
62+
'strings': ('OK',),
63+
})
64+
return
65+
self.insert('end', data)
66+
self.pos = self.index('end')
67+
self.yview_pickplace('end')
68+
69+
def inputhandler(self, *args):
70+
if not self.pid:
71+
Dialog(self.master, {
72+
'text': "No active process",
73+
'title': "No process",
74+
'bitmap': 'error',
75+
'default': 0,
76+
'strings': ('OK',),
77+
})
78+
return
79+
self.insert('end', '\n')
80+
line = self.get(self.pos, 'end')
81+
self.pos = self.index('end')
82+
os.write(self.tochild, line)
83+
84+
def sendeof(self, *args):
85+
if not self.pid:
86+
Dialog(self.master, {
87+
'text': "No active process",
88+
'title': "No process",
89+
'bitmap': 'error',
90+
'default': 0,
91+
'strings': ('OK',),
92+
})
93+
return
94+
os.close(self.tochild)
95+
96+
def sendsig(self, sig):
97+
if not self.pid:
98+
Dialog(self.master, {
99+
'text': "No active process",
100+
'title': "No process",
101+
'bitmap': 'error',
102+
'default': 0,
103+
'strings': ('OK',),
104+
})
105+
return
106+
os.kill(self.pid, sig)
107+
108+
def sigint(self, *args):
109+
self.sendsig(signal.SIGINT)
110+
111+
def sigquit(self, *args):
112+
self.sendsig(signal.SIGQUIT)
113+
114+
def sigterm(self, *args):
115+
self.sendsig(signal.SIGTERM)
116+
117+
def sigkill(self, *args):
118+
self.sendsig(signal.SIGKILL)
119+
120+
MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???)
121+
122+
def spawn(prog, args):
123+
p2cread, p2cwrite = os.pipe()
124+
c2pread, c2pwrite = os.pipe()
125+
pid = os.fork()
126+
if pid == 0:
127+
# Child
128+
os.close(0)
129+
os.close(1)
130+
os.close(2)
131+
if os.dup(p2cread) <> 0:
132+
sys.stderr.write('popen2: bad read dup\n')
133+
if os.dup(c2pwrite) <> 1:
134+
sys.stderr.write('popen2: bad write dup\n')
135+
if os.dup(c2pwrite) <> 2:
136+
sys.stderr.write('popen2: bad write dup\n')
137+
for i in range(3, MAXFD):
138+
try:
139+
os.close(i)
140+
except:
141+
pass
142+
try:
143+
os.execvp(prog, args)
144+
finally:
145+
print 'execvp failed'
146+
os._exit(1)
147+
os.close(p2cread)
148+
os.close(c2pwrite)
149+
return pid, c2pread, p2cwrite
150+
151+
def test():
152+
shell = string.join(sys.argv[1:])
153+
cnf = {}
154+
if shell:
155+
cnf['shell'] = shell
156+
root = Tk()
157+
root.minsize(1, 1)
158+
w = ShellWindow(root, cnf)
159+
w.pack({'expand': 1, 'fill': 'both'})
160+
w.focus_set()
161+
w.tk.mainloop()
162+
163+
if __name__ == '__main__':
164+
test()

0 commit comments

Comments
 (0)