home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / tkinter / guido / ShellWindow.py < prev    next >
Text File  |  1997-10-07  |  3KB  |  152 lines

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