 3b0f80e19f
			
		
	
	
		3b0f80e19f
		
			
		
	
	
	
	
		
			
			Both Archlinux and Fedora 29 have guidelines to point explicitly at /usr/bin/python2 where it expect python2. Also, do not use env. Fixes QubesOS/qubes-issues#4027
		
			
				
	
	
		
			46 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			46 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python2
 | |
| # Send the command to the remote side, and then transfer stdin from local to
 | |
| # remote and stdout from remote to local.
 | |
| #
 | |
| # The tricky part is delimiting the command from the stdin data.  If we were
 | |
| # implementing this from scratch, we'd probably use a null byte.  However, we'd
 | |
| # like to work with the existing qubes.VMShell service, whose implementation is
 | |
| # simply "/bin/bash", so users don't have to maintain duplicate RPC policy.  We
 | |
| # take advantage of the fact that when bash is executing commands from a pipe,
 | |
| # it reads one character at a time until it gets a newline that ends a command.
 | |
| # So the initial qubes.VMShell bash process, which is executing commands from
 | |
| # stdin, consumes exactly the line from the "write" below and then either
 | |
| # completes the "exec" or exits.  In no event does it touch the stdin data
 | |
| # intended for the command.
 | |
| 
 | |
| import os
 | |
| import subprocess
 | |
| import sys
 | |
| 
 | |
| cmd = ' '.join(sys.argv[1:])
 | |
| sys.stdout.write("exec bash -c '%s' || exit 127\n" % cmd.replace("'", "'\\''"))
 | |
| sys.stdout.flush()
 | |
| 
 | |
| local_stdin = int(os.environ['SAVED_FD_0'])
 | |
| local_stdout = int(os.environ['SAVED_FD_1'])
 | |
| stdin_sender = subprocess.Popen(['cat'], stdin=local_stdin)
 | |
| stdout_receiver = subprocess.Popen(['cat'], stdout=local_stdout)
 | |
| 
 | |
| # sys.std{in,out}.close() do not close the FDs, but they apparently stop Python
 | |
| # from trying to close the FDs again on exit and generating an exception.
 | |
| sys.stdin.close()
 | |
| sys.stdout.close()
 | |
| os.close(0)
 | |
| # The really important step, so this process doesn't prevent qrexec-client-vm
 | |
| # from seeing EOF on input.
 | |
| os.close(1)
 | |
| os.close(local_stdin)
 | |
| os.close(local_stdout)
 | |
| 
 | |
| stdout_receiver.wait()
 | |
| # With the current Qubes RPC implementation, the stdout receiver doesn't get EOF
 | |
| # until the remote process has exited.  At that point, we want to finish and not
 | |
| # try to send more input.  This is the same behavior ssh appears to have.
 | |
| stdin_sender.terminate()
 | |
| stdin_sender.wait()
 |