diff options
Diffstat (limited to 'Demo')
-rwxr-xr-x | Demo/tkinter/guido/ShellWindow.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/Demo/tkinter/guido/ShellWindow.py b/Demo/tkinter/guido/ShellWindow.py new file mode 100755 index 0000000..93a13d6 --- /dev/null +++ b/Demo/tkinter/guido/ShellWindow.py @@ -0,0 +1,164 @@ +import os +import sys +import string +from Tkinter import * +from ScrolledText import ScrolledText +from Dialog import Dialog +import signal + +TK_READABLE = 1 +TK_WRITABLE = 2 +TK_EXCEPTION = 4 + +BUFSIZE = 512 + +class ShellWindow(ScrolledText): + + def __init__(self, master = None, cnf = {}): + try: + shell = cnf['shell'] + del cnf['shell'] + except KeyError: + try: + shell = os.environ['SHELL'] + except KeyError: + shell = '/bin/sh' + shell = shell + ' -i' + args = string.split(shell) + shell = args[0] + + ScrolledText.__init__(self, master, cnf) + self.pos = '1.0' + self.bind('<Return>', self.inputhandler) + self.bind('<Control-c>', self.sigint) + self.bind('<Control-t>', self.sigterm) + self.bind('<Control-k>', self.sigkill) + self.bind('<Control-d>', self.sendeof) + + self.pid, self.fromchild, self.tochild = spawn(shell, args) + self.tk.createfilehandler(self.fromchild, TK_READABLE, + self.outputhandler) + + def outputhandler(self, file, mask): + data = os.read(file, BUFSIZE) + if not data: + self.tk.deletefilehandler(file) + pid, sts = os.waitpid(self.pid, 0) + print 'pid', pid, 'status', sts + self.pid = None + detail = sts>>8 + cause = sts & 0xff + if cause == 0: + msg = "exit status %d" % detail + else: + msg = "killed by signal %d" % (cause & 0x7f) + if cause & 0x80: + msg = msg + " -- core dumped" + Dialog(self.master, { + 'text': msg, + 'title': "Exit status", + 'bitmap': 'warning', + 'default': 0, + 'strings': ('OK',), + }) + return + self.insert('end', data) + self.pos = self.index('end') + self.yview_pickplace('end') + + def inputhandler(self, *args): + if not self.pid: + Dialog(self.master, { + 'text': "No active process", + 'title': "No process", + 'bitmap': 'error', + 'default': 0, + 'strings': ('OK',), + }) + return + self.insert('end', '\n') + line = self.get(self.pos, 'end') + self.pos = self.index('end') + os.write(self.tochild, line) + + def sendeof(self, *args): + if not self.pid: + Dialog(self.master, { + 'text': "No active process", + 'title': "No process", + 'bitmap': 'error', + 'default': 0, + 'strings': ('OK',), + }) + return + os.close(self.tochild) + + def sendsig(self, sig): + if not self.pid: + Dialog(self.master, { + 'text': "No active process", + 'title': "No process", + 'bitmap': 'error', + 'default': 0, + 'strings': ('OK',), + }) + return + os.kill(self.pid, sig) + + def sigint(self, *args): + self.sendsig(signal.SIGINT) + + def sigquit(self, *args): + self.sendsig(signal.SIGQUIT) + + def sigterm(self, *args): + self.sendsig(signal.SIGTERM) + + def sigkill(self, *args): + self.sendsig(signal.SIGKILL) + +MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???) + +def spawn(prog, args): + p2cread, p2cwrite = os.pipe() + c2pread, c2pwrite = os.pipe() + pid = os.fork() + if pid == 0: + # Child + os.close(0) + os.close(1) + os.close(2) + if os.dup(p2cread) <> 0: + sys.stderr.write('popen2: bad read dup\n') + if os.dup(c2pwrite) <> 1: + sys.stderr.write('popen2: bad write dup\n') + if os.dup(c2pwrite) <> 2: + sys.stderr.write('popen2: bad write dup\n') + for i in range(3, MAXFD): + try: + os.close(i) + except: + pass + try: + os.execvp(prog, args) + finally: + print 'execvp failed' + os._exit(1) + os.close(p2cread) + os.close(c2pwrite) + return pid, c2pread, p2cwrite + +def test(): + shell = string.join(sys.argv[1:]) + cnf = {} + if shell: + cnf['shell'] = shell + root = Tk() + root.minsize(1, 1) + w = ShellWindow(root, cnf) + w.pack({'expand': 1, 'fill': 'both'}) + w.focus_set() + w.tk.mainloop() + +if __name__ == '__main__': + test() |