| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | from Tkinter import * | 
					
						
							|  |  |  | from ScrolledText import ScrolledText | 
					
						
							|  |  |  | from Dialog import Dialog | 
					
						
							|  |  |  | import signal | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BUFSIZE = 512 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ShellWindow(ScrolledText): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 	def __init__(self, master=None, shell=None, **cnf): | 
					
						
							|  |  |  | 		if not shell: | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 			try: | 
					
						
							|  |  |  | 				shell = os.environ['SHELL'] | 
					
						
							|  |  |  | 			except KeyError: | 
					
						
							|  |  |  | 				shell = '/bin/sh' | 
					
						
							|  |  |  | 			shell = shell + ' -i' | 
					
						
							|  |  |  | 		args = string.split(shell) | 
					
						
							|  |  |  | 		shell = args[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		apply(ScrolledText.__init__, (self, master), cnf) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 		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) | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		self.tk.createfilehandler(self.fromchild, READABLE, | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 					  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" | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 			Dialog(self.master, | 
					
						
							|  |  |  | 			       text=msg, | 
					
						
							|  |  |  | 			       title="Exit status", | 
					
						
							|  |  |  | 			       bitmap='warning', | 
					
						
							|  |  |  | 			       default=0, | 
					
						
							|  |  |  | 			       strings=('OK',)) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		self.insert(END, data) | 
					
						
							|  |  |  | 		self.pos = self.index("end - 1 char") | 
					
						
							|  |  |  | 		self.yview_pickplace(END) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def inputhandler(self, *args): | 
					
						
							|  |  |  | 		if not self.pid: | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 			self.no_process() | 
					
						
							|  |  |  | 			return "break" | 
					
						
							|  |  |  | 		self.insert(END, "\n") | 
					
						
							|  |  |  | 		line = self.get(self.pos, "end - 1 char") | 
					
						
							|  |  |  | 		self.pos = self.index(END) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 		os.write(self.tochild, line) | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return "break" | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sendeof(self, *args): | 
					
						
							|  |  |  | 		if not self.pid: | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 			self.no_process() | 
					
						
							|  |  |  | 			return "break" | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 		os.close(self.tochild) | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return "break" | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sendsig(self, sig): | 
					
						
							|  |  |  | 		if not self.pid: | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 			self.no_process() | 
					
						
							|  |  |  | 			return "break" | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 		os.kill(self.pid, sig) | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return "break" | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sigint(self, *args): | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return self.sendsig(signal.SIGINT) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sigquit(self, *args): | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return self.sendsig(signal.SIGQUIT) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sigterm(self, *args): | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		return self.sendsig(signal.SIGTERM) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def sigkill(self, *args): | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 		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',)) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											1997-10-07 14:37:31 +00:00
										 |  |  | 		for i in 0, 1, 2: | 
					
						
							|  |  |  | 		    try: | 
					
						
							|  |  |  | 			os.close(i) | 
					
						
							|  |  |  | 		    except os.error: | 
					
						
							|  |  |  | 			pass | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 		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: | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 			sys.stderr.write('execvp failed\n') | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 			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) | 
					
						
							| 
									
										
										
										
											1996-07-30 18:57:18 +00:00
										 |  |  | 	if shell: | 
					
						
							|  |  |  | 	    w = ShellWindow(root, shell=shell) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 	    w = ShellWindow(root) | 
					
						
							|  |  |  | 	w.pack(expand=1, fill=BOTH) | 
					
						
							| 
									
										
										
										
											1995-01-10 17:08:10 +00:00
										 |  |  | 	w.focus_set() | 
					
						
							|  |  |  | 	w.tk.mainloop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  | 	test() |