Spawn a shell server and forward input/output from/to the TCP socket.
(self, unused_var)
| 735 | os._exit(0) # pylint: disable=protected-access |
| 736 | |
| 737 | def SpawnShellServer(self, unused_var): |
| 738 | """Spawn a shell server and forward input/output from/to the TCP socket.""" |
| 739 | logging.info('SpawnShellServer: started') |
| 740 | |
| 741 | # Add ghost executable to PATH |
| 742 | script_dir = os.path.dirname(os.path.abspath(sys.argv[0])) |
| 743 | env = os.environ.copy() |
| 744 | env['PATH'] = '%s:%s' % (script_dir, os.getenv('PATH')) |
| 745 | |
| 746 | # Execute shell command from HOME directory |
| 747 | os.chdir(os.getenv('HOME', '/tmp')) |
| 748 | |
| 749 | p = subprocess.Popen(self._shell_command, |
| 750 | stdin=subprocess.PIPE, |
| 751 | stdout=subprocess.PIPE, |
| 752 | stderr=subprocess.PIPE, |
| 753 | shell=True, |
| 754 | env=env) |
| 755 | |
| 756 | def make_non_block(fd): |
| 757 | fl = fcntl.fcntl(fd, fcntl.F_GETFL) |
| 758 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
| 759 | |
| 760 | make_non_block(p.stdout) |
| 761 | make_non_block(p.stderr) |
| 762 | |
| 763 | try: |
| 764 | p.stdin.write(self._sock.RecvBuf()) |
| 765 | |
| 766 | stdin_open = True |
| 767 | sock_readable = True |
| 768 | |
| 769 | while True: |
| 770 | read_fds = [p.stdout, p.stderr] |
| 771 | if sock_readable: |
| 772 | read_fds.append(self._sock) |
| 773 | |
| 774 | rd, unused_wd, unused_xd = select.select(read_fds, [], []) |
| 775 | |
| 776 | if p.stdout in rd: |
| 777 | self._sock.Send(p.stdout.read(_BUFSIZE)) |
| 778 | |
| 779 | if p.stderr in rd: |
| 780 | self._sock.Send(p.stderr.read(_BUFSIZE)) |
| 781 | |
| 782 | if self._sock in rd: |
| 783 | ret = self._sock.Recv(_BUFSIZE) |
| 784 | if not ret: |
| 785 | # TCP half-close: read side got EOF, close subprocess stdin |
| 786 | if stdin_open: |
| 787 | logging.info('SpawnShellServer: input EOF, closing stdin') |
| 788 | p.stdin.close() |
| 789 | stdin_open = False |
| 790 | sock_readable = False |
| 791 | else: |
| 792 | if stdin_open: |
| 793 | p.stdin.write(ret) |
| 794 |