| Viewing file:  ShellWindow.py (4.07 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
import osimport sys
 import string
 from Tkinter import *
 from ScrolledText import ScrolledText
 from Dialog import Dialog
 import signal
 
 BUFSIZE = 512
 
 class ShellWindow(ScrolledText):
 
 def __init__(self, master=None, shell=None, **cnf):
 if not shell:
 try:
 shell = os.environ['SHELL']
 except KeyError:
 shell = '/bin/sh'
 shell = shell + ' -i'
 args = string.split(shell)
 shell = args[0]
 
 apply(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, 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 - 1 char")
 self.yview_pickplace(END)
 
 def inputhandler(self, *args):
 if not self.pid:
 self.no_process()
 return "break"
 self.insert(END, "\n")
 line = self.get(self.pos, "end - 1 char")
 self.pos = self.index(END)
 os.write(self.tochild, line)
 return "break"
 
 def sendeof(self, *args):
 if not self.pid:
 self.no_process()
 return "break"
 os.close(self.tochild)
 return "break"
 
 def sendsig(self, sig):
 if not self.pid:
 self.no_process()
 return "break"
 os.kill(self.pid, sig)
 return "break"
 
 def sigint(self, *args):
 return self.sendsig(signal.SIGINT)
 
 def sigquit(self, *args):
 return self.sendsig(signal.SIGQUIT)
 
 def sigterm(self, *args):
 return self.sendsig(signal.SIGTERM)
 
 def sigkill(self, *args):
 return self.sendsig(signal.SIGKILL)
 
 def no_process(self):
 Dialog(self.master,
 text="No active process",
 title="No process",
 bitmap='error',
 default=0,
 strings=('OK',))
 
 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
 for i in 0, 1, 2:
 try:
 os.close(i)
 except os.error:
 pass
 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')
 os.closerange(3, MAXFD)
 try:
 os.execvp(prog, args)
 finally:
 sys.stderr.write('execvp failed\n')
 os._exit(1)
 os.close(p2cread)
 os.close(c2pwrite)
 return pid, c2pread, p2cwrite
 
 def test():
 shell = string.join(sys.argv[1:])
 root = Tk()
 root.minsize(1, 1)
 if shell:
 w = ShellWindow(root, shell=shell)
 else:
 w = ShellWindow(root)
 w.pack(expand=1, fill=BOTH)
 w.focus_set()
 w.tk.mainloop()
 
 if __name__ == '__main__':
 test()
 
 |