mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 02:15:10 +00:00 
			
		
		
		
	 9c6bd77e39
			
		
	
	
		9c6bd77e39
		
	
	
	
	
		
			
			svn+ssh://pythondev@svn.python.org/python/trunk ........ r78779 | benjamin.peterson | 2010-03-07 20:11:06 -0600 (Sun, 07 Mar 2010) | 1 line remove svn:executable from scripts without a shebang line ........
		
			
				
	
	
		
			147 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| import sys
 | |
| import string
 | |
| from tkinter import *
 | |
| from tkinter.scrolledtext import ScrolledText
 | |
| from tkinter.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]
 | |
| 
 | |
|         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()
 |