mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	demonstrate shell in a Tk window
This commit is contained in:
		
							parent
							
								
									b8fe9b3fc8
								
							
						
					
					
						commit
						630112ed04
					
				
					 1 changed files with 164 additions and 0 deletions
				
			
		
							
								
								
									
										164
									
								
								Demo/tkinter/guido/ShellWindow.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										164
									
								
								Demo/tkinter/guido/ShellWindow.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -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() | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum