Example #1
0
    def _spawnAsBatch(self, processProtocol, executable, args, env,
                      path, usePTY):
        """A cheat that routes around the impedance mismatch between
        twisted and cmd.exe with respect to escaping quotes"""

        tf = NamedTemporaryFile(dir='.', suffix=".bat", delete=False)
        # echo off hides this cheat from the log files.
        tf.write("@echo off\n")
        if type(self.command) in types.StringTypes:
            tf.write(self.command)
        else:
            def maybe_escape_pipes(arg):
                if arg != '|':
                    return arg.replace('|', '^|')
                else:
                    return '|'
            cmd = [maybe_escape_pipes(arg) for arg in self.command]
            tf.write(quoteArguments(cmd))
        tf.close()

        argv = os.environ['COMSPEC'].split()  # allow %COMSPEC% to have args
        if '/c' not in argv:
            argv += ['/c']
        argv += [tf.name]

        def unlink_temp(result):
            os.unlink(tf.name)
            return result
        self.deferred.addBoth(unlink_temp)

        return reactor.spawnProcess(processProtocol, executable, argv, env,
                                    path, usePTY=usePTY)
Example #2
0
 def escape_arg(arg):
     arg = bytes2NativeString(arg, unicode_encoding)
     arg = quoteArguments([arg])
     # escape shell special characters
     arg = re.sub(r'[@()^"<>&|]', r'^\g<0>', arg)
     # prevent variable expansion
     return arg.replace('%', '%%')
Example #3
0
 def escape_arg(arg):
     arg = bytes2NativeString(arg, unicode_encoding)
     arg = quoteArguments([arg])
     # escape shell special characters
     arg = re.sub(r'[@()^"<>&|]', r'^\g<0>', arg)
     # prevent variable expansion
     return arg.replace('%', '%%')
Example #4
0
    def _spawnAsBatch(self, processProtocol, executable, args, env,
            path, usePTY):
        """A cheat that routes around the impedance mismatch between
        twisted and cmd.exe with respect to escaping quotes"""

        tf = NamedTemporaryFile(dir='.',suffix=".bat",delete=False)
        #echo off hides this cheat from the log files.
        tf.write( "@echo off\n" )
        if type(self.command) in types.StringTypes:
            tf.write( self.command )
        else:
            def maybe_escape_pipes(arg):
                if arg != '|':
                    return arg.replace('|','^|')
                else:
                    return '|'
            cmd = [maybe_escape_pipes(arg) for arg in self.command]
            tf.write( quoteArguments(cmd) )
        tf.close()

        argv = os.environ['COMSPEC'].split() # allow %COMSPEC% to have args
        if '/c' not in argv: argv += ['/c']
        argv += [tf.name]

        def unlink_temp(result):
            os.unlink(tf.name)
            return result
        self.deferred.addBoth(unlink_temp)

        return reactor.spawnProcess(processProtocol, executable, argv, env,
                                    path, usePTY=usePTY)
Example #5
0
    def escape_arg(arg):
        if arg == '|':
            return arg

        arg = quoteArguments([arg])
        # escape shell special characters
        arg = re.sub(r'[@()^"<>&|]', r'^\g<0>', arg)
        # prevent variable expansion
        return arg.replace('%', '%%')
Example #6
0
    def escape_arg(arg):
        if arg == '|':
            return arg

        arg = quoteArguments([arg])
        # escape shell special characters
        arg = re.sub(r'[@()^"<>&|]', r'^\g<0>', arg)
        # prevent variable expansion
        return arg.replace('%', '%%')
Example #7
0
    def escape_arg(arg):
        if arg == "|":
            return arg

        arg = quoteArguments([arg])
        # escape shell special characters
        arg = re.sub(r'[@()^"<>&|]', r"^\g<0>", arg)
        # prevent variable expansion
        return arg.replace("%", "%%")
Example #8
0
    def __init__(self, reactor, protocol, command, args, environment, path):
        """
        Create a new child process.
        """
        _pollingfile._PollingTimer.__init__(self, reactor)
        BaseProcess.__init__(self, protocol)

        # security attributes for pipes
        sAttrs = win32security.SECURITY_ATTRIBUTES()
        sAttrs.bInheritHandle = 1

        # create the pipes which will connect to the secondary process
        self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
        self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
        hStdinR, self.hStdinW = win32pipe.CreatePipe(sAttrs, 0)

        win32pipe.SetNamedPipeHandleState(self.hStdinW, win32pipe.PIPE_NOWAIT,
                                          None, None)

        # set the info structure for the new process.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = hStdoutW
        StartupInfo.hStdError = hStderrW
        StartupInfo.hStdInput = hStdinR
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

        # Create new handles whose inheritance property is false
        currentPid = win32api.GetCurrentProcess()

        tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid,
                                       0, 0, win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdoutR)
        self.hStdoutR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid,
                                       0, 0, win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStderrR)
        self.hStderrR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0,
                                       0, win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdinW)
        self.hStdinW = tmp

        # Add the specified environment to the current environment - this is
        # necessary because certain operations are only supported on Windows
        # if certain environment variables are present.

        env = os.environ.copy()
        env.update(environment or {})
        env = {
            os.fsdecode(key): os.fsdecode(value)
            for key, value in env.items()
        }

        # Make sure all the arguments are Unicode.
        args = [os.fsdecode(x) for x in args]

        cmdline = quoteArguments(args)

        # The command, too, needs to be Unicode, if it is a value.
        command = os.fsdecode(command) if command else command
        path = os.fsdecode(path) if path else path

        # TODO: error detection here.  See #2787 and #4184.
        def doCreate():
            flags = win32con.CREATE_NO_WINDOW
            self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
                command, cmdline, None, None, 1, flags, env, path, StartupInfo)

        try:
            doCreate()
        except pywintypes.error as pwte:
            if not _invalidWin32App(pwte):
                # This behavior isn't _really_ documented, but let's make it
                # consistent with the behavior that is documented.
                raise OSError(pwte)
            else:
                # look for a shebang line.  Insert the original 'command'
                # (actually a script) into the new arguments list.
                sheb = _findShebang(command)
                if sheb is None:
                    raise OSError("%r is neither a Windows executable, "
                                  "nor a script with a shebang line" % command)
                else:
                    args = list(args)
                    args.insert(0, command)
                    cmdline = quoteArguments(args)
                    origcmd = command
                    command = sheb
                    try:
                        # Let's try again.
                        doCreate()
                    except pywintypes.error as pwte2:
                        # d'oh, failed again!
                        if _invalidWin32App(pwte2):
                            raise OSError("%r has an invalid shebang line: "
                                          "%r is not a valid executable" %
                                          (origcmd, sheb))
                        raise OSError(pwte2)

        # close handles which only the child will use
        win32file.CloseHandle(hStderrW)
        win32file.CloseHandle(hStdoutW)
        win32file.CloseHandle(hStdinR)

        # set up everything
        self.stdout = _pollingfile._PollableReadPipe(
            self.hStdoutR,
            lambda data: self.proto.childDataReceived(1, data),
            self.outConnectionLost,
        )

        self.stderr = _pollingfile._PollableReadPipe(
            self.hStderrR,
            lambda data: self.proto.childDataReceived(2, data),
            self.errConnectionLost,
        )

        self.stdin = _pollingfile._PollableWritePipe(self.hStdinW,
                                                     self.inConnectionLost)

        for pipewatcher in self.stdout, self.stderr, self.stdin:
            self._addPollableResource(pipewatcher)

        # notify protocol
        self.proto.makeConnection(self)

        self._addPollableResource(_Reaper(self))
Example #9
0
    def __init__(self, reactor, protocol, command, args, environment, path):
        _pollingfile._PollingTimer.__init__(self, reactor)
        BaseProcess.__init__(self, protocol)

        # security attributes for pipes
        sAttrs = win32security.SECURITY_ATTRIBUTES()
        sAttrs.bInheritHandle = 1

        # create the pipes which will connect to the secondary process
        self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
        self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
        hStdinR,  self.hStdinW  = win32pipe.CreatePipe(sAttrs, 0)

        win32pipe.SetNamedPipeHandleState(self.hStdinW,
                                          win32pipe.PIPE_NOWAIT,
                                          None,
                                          None)

        # set the info structure for the new process.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = hStdoutW
        StartupInfo.hStdError  = hStderrW
        StartupInfo.hStdInput  = hStdinR
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

        # Create new handles whose inheritance property is false
        currentPid = win32api.GetCurrentProcess()

        tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdoutR)
        self.hStdoutR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStderrR)
        self.hStderrR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdinW)
        self.hStdinW = tmp

        # Add the specified environment to the current environment - this is
        # necessary because certain operations are only supported on Windows
        # if certain environment variables are present.

        env = os.environ.copy()
        env.update(environment or {})

        cmdline = quoteArguments(args)
        # TODO: error detection here.
        def doCreate():
            self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
                command, cmdline, None, None, 1, 0, env, path, StartupInfo)
        try:
            doCreate()
        except pywintypes.error, pwte:
            if not _invalidWin32App(pwte):
                # This behavior isn't _really_ documented, but let's make it
                # consistent with the behavior that is documented.
                raise OSError(pwte)
            else:
                # look for a shebang line.  Insert the original 'command'
                # (actually a script) into the new arguments list.
                sheb = _findShebang(command)
                if sheb is None:
                    raise OSError(
                        "%r is neither a Windows executable, "
                        "nor a script with a shebang line" % command)
                else:
                    args = list(args)
                    args.insert(0, command)
                    cmdline = quoteArguments(args)
                    origcmd = command
                    command = sheb
                    try:
                        # Let's try again.
                        doCreate()
                    except pywintypes.error, pwte2:
                        # d'oh, failed again!
                        if _invalidWin32App(pwte2):
                            raise OSError(
                                "%r has an invalid shebang line: "
                                "%r is not a valid executable" % (
                                    origcmd, sheb))
                        raise OSError(pwte2)
    def __init__(self, reactor, protocol, command, args, environment, path):
        """
        Create a new child process.
        """
        _pollingfile._PollingTimer.__init__(self, reactor)
        BaseProcess.__init__(self, protocol)

        # security attributes for pipes
        sAttrs = win32security.SECURITY_ATTRIBUTES()
        sAttrs.bInheritHandle = 1

        # create the pipes which will connect to the secondary process
        self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
        self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
        hStdinR, self.hStdinW  = win32pipe.CreatePipe(sAttrs, 0)

        win32pipe.SetNamedPipeHandleState(self.hStdinW,
                                          win32pipe.PIPE_NOWAIT,
                                          None,
                                          None)

        # set the info structure for the new process.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = hStdoutW
        StartupInfo.hStdError  = hStderrW
        StartupInfo.hStdInput  = hStdinR
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

        # Create new handles whose inheritance property is false
        currentPid = win32api.GetCurrentProcess()

        tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdoutR)
        self.hStdoutR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStderrR)
        self.hStderrR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdinW)
        self.hStdinW = tmp

        # Add the specified environment to the current environment - this is
        # necessary because certain operations are only supported on Windows
        # if certain environment variables are present.

        env = os.environ.copy()
        env.update(environment or {})
        newenv = {}
        for key, value in items(env):

            key = _fsdecode(key)
            value = _fsdecode(value)

            newenv[key] = value

        env = newenv

        # Make sure all the arguments are Unicode.
        args = [_fsdecode(x) for x in args]

        cmdline = quoteArguments(args)

        # The command, too, needs to be Unicode, if it is a value.
        command = _fsdecode(command) if command else command
        path = _fsdecode(path) if path else path

        # TODO: error detection here.  See #2787 and #4184.
        def doCreate():
            flags = win32con.CREATE_NO_WINDOW
            self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
                command, cmdline, None, None, 1, flags, env, path, StartupInfo)
        try:
            doCreate()
        except pywintypes.error as pwte:
            if not _invalidWin32App(pwte):
                # This behavior isn't _really_ documented, but let's make it
                # consistent with the behavior that is documented.
                raise OSError(pwte)
            else:
                # look for a shebang line.  Insert the original 'command'
                # (actually a script) into the new arguments list.
                sheb = _findShebang(command)
                if sheb is None:
                    raise OSError(
                        "%r is neither a Windows executable, "
                        "nor a script with a shebang line" % command)
                else:
                    args = list(args)
                    args.insert(0, command)
                    cmdline = quoteArguments(args)
                    origcmd = command
                    command = sheb
                    try:
                        # Let's try again.
                        doCreate()
                    except pywintypes.error as pwte2:
                        # d'oh, failed again!
                        if _invalidWin32App(pwte2):
                            raise OSError(
                                "%r has an invalid shebang line: "
                                "%r is not a valid executable" % (
                                    origcmd, sheb))
                        raise OSError(pwte2)

        # close handles which only the child will use
        win32file.CloseHandle(hStderrW)
        win32file.CloseHandle(hStdoutW)
        win32file.CloseHandle(hStdinR)

        # set up everything
        self.stdout = _pollingfile._PollableReadPipe(
            self.hStdoutR,
            lambda data: self.proto.childDataReceived(1, data),
            self.outConnectionLost)

        self.stderr = _pollingfile._PollableReadPipe(
                self.hStderrR,
                lambda data: self.proto.childDataReceived(2, data),
                self.errConnectionLost)

        self.stdin = _pollingfile._PollableWritePipe(
            self.hStdinW, self.inConnectionLost)

        for pipewatcher in self.stdout, self.stderr, self.stdin:
            self._addPollableResource(pipewatcher)

        # notify protocol
        self.proto.makeConnection(self)

        self._addPollableResource(_Reaper(self))
Example #11
0
  def __new_init__(self, reactor, protocol, command, args, environment, path):
      _pollingfile._PollingTimer.__init__(self, reactor)
      self.proto = protocol
      self.protocol = protocol

      # security attributes for pipes
      sAttrs = win32security.SECURITY_ATTRIBUTES()
      sAttrs.bInheritHandle = 1

      # create the pipes which will connect to the secondary process
      self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
      self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
      hStdinR,  self.hStdinW  = win32pipe.CreatePipe(sAttrs, 0)

      win32pipe.SetNamedPipeHandleState(self.hStdinW,
                                        win32pipe.PIPE_NOWAIT,
                                        None,
                                        None)

      # set the info structure for the new process.
      StartupInfo = win32process.STARTUPINFO()
      StartupInfo.hStdOutput = hStdoutW
      StartupInfo.hStdError  = hStderrW
      StartupInfo.hStdInput  = hStdinR
      StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

      # Create new handles whose inheritance property is false
      currentPid = win32api.GetCurrentProcess()

      tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
                                     win32con.DUPLICATE_SAME_ACCESS)
      win32file.CloseHandle(self.hStdoutR)
      self.hStdoutR = tmp

      tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
                                     win32con.DUPLICATE_SAME_ACCESS)
      win32file.CloseHandle(self.hStderrR)
      self.hStderrR = tmp

      tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
                                     win32con.DUPLICATE_SAME_ACCESS)
      win32file.CloseHandle(self.hStdinW)
      self.hStdinW = tmp

      # Add the specified environment to the current environment - this is
      # necessary because certain operations are only supported on Windows
      # if certain environment variables are present.

      env = os.environ.copy()
      env.update(environment or {})

      cmdline = quoteArguments(args)
      # TODO: error detection here.
      def doCreate():
          for key in env.keys():
            if type(env[key]) == type(u"string"):
              env[key] = env[key].encode('MBCS')
          self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
              command, cmdline, None, None, 1, win32process.CREATE_NO_WINDOW, env, path, StartupInfo)
      try:
          doCreate()
      except pywintypes.error, pwte:
          if not twisted.internet._dumbwin32proc._invalidWin32App(pwte):
              # This behavior isn't _really_ documented, but let's make it
              # consistent with the behavior that is documented.
              raise OSError(pwte)
          else:
              # look for a shebang line.  Insert the original 'command'
              # (actually a script) into the new arguments list.
              sheb = twisted.internet._dumbwin32proc._findShebang(command)
              if sheb is None:
                  raise OSError(
                      "%r is neither a Windows executable, "
                      "nor a script with a shebang line" % command)
              else:
                  args = list(args)
                  args.insert(0, command)
                  cmdline = quoteArguments(args)
                  origcmd = command
                  command = sheb
                  try:
                      # Let's try again.
                      doCreate()
                  except pywintypes.error, pwte2:
                      # d'oh, failed again!
                      if twisted.internet._dumbwin32proc._invalidWin32App(pwte2):
                          raise OSError(
                              "%r has an invalid shebang line: "
                              "%r is not a valid executable" % (
                                  origcmd, sheb))
                      raise OSError(pwte2)
    def __init__(self, reactor, protocol, command, args, environment, path):
        """
        Create a new child process.
        """
        _pollingfile._PollingTimer.__init__(self, reactor)
        BaseProcess.__init__(self, protocol)

        # security attributes for pipes
        sAttrs = win32security.SECURITY_ATTRIBUTES()
        sAttrs.bInheritHandle = 1

        # create the pipes which will connect to the secondary process
        self.hStdoutR, hStdoutW = win32pipe.CreatePipe(sAttrs, 0)
        self.hStderrR, hStderrW = win32pipe.CreatePipe(sAttrs, 0)
        hStdinR,  self.hStdinW  = win32pipe.CreatePipe(sAttrs, 0)

        win32pipe.SetNamedPipeHandleState(self.hStdinW,
                                          win32pipe.PIPE_NOWAIT,
                                          None,
                                          None)

        # set the info structure for the new process.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = hStdoutW
        StartupInfo.hStdError  = hStderrW
        StartupInfo.hStdInput  = hStdinR
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

        # Create new handles whose inheritance property is false
        currentPid = win32api.GetCurrentProcess()

        tmp = win32api.DuplicateHandle(currentPid, self.hStdoutR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdoutR)
        self.hStdoutR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStderrR, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStderrR)
        self.hStderrR = tmp

        tmp = win32api.DuplicateHandle(currentPid, self.hStdinW, currentPid, 0, 0,
                                       win32con.DUPLICATE_SAME_ACCESS)
        win32file.CloseHandle(self.hStdinW)
        self.hStdinW = tmp

        # Add the specified environment to the current environment - this is
        # necessary because certain operations are only supported on Windows
        # if certain environment variables are present.

        env = os.environ.copy()
        env.update(environment or {})

        cmdline = quoteArguments(args)
        # TODO: error detection here.  See #2787 and #4184.
        def doCreate():
            self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
                command, cmdline, None, None, 1, 0, env, path, StartupInfo)
        try:
            try:
                doCreate()
            except TypeError, e:
                # win32process.CreateProcess cannot deal with mixed
                # str/unicode environment, so we make it all Unicode
                if e.args != ('All dictionary items must be strings, or '
                              'all must be unicode',):
                    raise
                newenv = {}
                for key, value in env.items():
                    newenv[unicode(key)] = unicode(value)
                env = newenv
                doCreate()
        except pywintypes.error, pwte:
            if not _invalidWin32App(pwte):
                # This behavior isn't _really_ documented, but let's make it
                # consistent with the behavior that is documented.
                raise OSError(pwte)
            else:
                # look for a shebang line.  Insert the original 'command'
                # (actually a script) into the new arguments list.
                sheb = _findShebang(command)
                if sheb is None:
                    raise OSError(
                        "%r is neither a Windows executable, "
                        "nor a script with a shebang line" % command)
                else:
                    args = list(args)
                    args.insert(0, command)
                    cmdline = quoteArguments(args)
                    origcmd = command
                    command = sheb
                    try:
                        # Let's try again.
                        doCreate()
                    except pywintypes.error, pwte2:
                        # d'oh, failed again!
                        if _invalidWin32App(pwte2):
                            raise OSError(
                                "%r has an invalid shebang line: "
                                "%r is not a valid executable" % (
                                    origcmd, sheb))
                        raise OSError(pwte2)
Example #13
0
    def __init__(self, reactor, protocol, command, args, environment, path):
        self.reactor = reactor
        self.protocol = protocol
        self.outBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        self.errBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        # This is the buffer for *reading* stdin, which is only done to
        # determine if the other end of the pipe was closed.
        self.inBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        # IO operation classes
        self.readOutOp = ops.ReadOutOp(self)
        self.readErrOp = ops.ReadErrOp(self)
        self.readInOp = ops.ReadInOp(self)
        self.writeInOp = ops.WriteInOp(self)

        self.writeBuffer = ""
        self.writing = False
        self.finished = False
        self.offset = 0
        self.writeBufferedSize = 0
        self.closingStdin = False
        self.closedStdin = False
        self.closedStdout = False
        self.closedStderr = False
        # Stdio handles
        self.hChildStdinRd = None
        self.hChildStdinWr = None
        self.hChildStdinWrDup = None
        self.hChildStdoutRd = None
        self.hChildStdoutWr = None
        self.hChildStdoutRdDup = None
        self.hChildStderrRd = None
        self.hChildStderrWr = None
        self.hChildStderrRdDup = None

        self.closedNotifies = 0  # increments to 3 (for stdin, stdout, stderr)
        self.closed = False  # set to true when all 3 handles close
        self.exited = False  # set to true when WFMO thread gets signalled proc handle.  See doWaitForProcessExit.

        # Set the bInheritHandle flag so pipe handles are inherited.
        saAttr = win32security.SECURITY_ATTRIBUTES()
        saAttr.bInheritHandle = 1

        currentPid = win32api.GetCurrentProcess(
        )  # -1 which stands for current process
        self.pid = os.getpid()  # unique pid for pipe naming

        # Create a pipe for the child process's STDOUT.
        self.stdoutPipeName = r"\\.\pipe\twisted-iocp-stdout-%d-%d-%d" % (
            self.pid, counter.next(), time.time())
        self.hChildStdoutRd = win32pipe.CreateNamedPipe(
            self.stdoutPipeName,
            win32con.PIPE_ACCESS_INBOUND
            | win32con.FILE_FLAG_OVERLAPPED,  # open mode
            win32con.PIPE_TYPE_BYTE,  # pipe mode
            1,  # max instances
            self.pipeBufferSize,  # out buffer size
            self.pipeBufferSize,  # in buffer size
            0,  # timeout 
            saAttr)

        self.hChildStdoutWr = win32file.CreateFile(
            self.stdoutPipeName, win32con.GENERIC_WRITE,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, saAttr,
            win32con.OPEN_EXISTING, win32con.FILE_FLAG_OVERLAPPED, 0)

        # Create noninheritable read handle and close the inheritable read
        # handle.
        self.hChildStdoutRdDup = win32api.DuplicateHandle(
            currentPid, self.hChildStdoutRd, currentPid, 0, 0,
            win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStdoutRd)
        self.hChildStdoutRd = self.hChildStdoutRdDup

        # Create a pipe for the child process's STDERR.
        self.stderrPipeName = r"\\.\pipe\twisted-iocp-stderr-%d-%d-%d" % (
            self.pid, counter.next(), time.time())
        self.hChildStderrRd = win32pipe.CreateNamedPipe(
            self.stderrPipeName,
            win32con.PIPE_ACCESS_INBOUND
            | win32con.FILE_FLAG_OVERLAPPED,  # open mode
            win32con.PIPE_TYPE_BYTE,  # pipe mode
            1,  # max instances
            self.pipeBufferSize,  # out buffer size
            self.pipeBufferSize,  # in buffer size
            0,  # timeout 
            saAttr)
        self.hChildStderrWr = win32file.CreateFile(
            self.stderrPipeName, win32con.GENERIC_WRITE,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, saAttr,
            win32con.OPEN_EXISTING, win32con.FILE_FLAG_OVERLAPPED, 0)

        # Create noninheritable read handle and close the inheritable read
        # handle.
        self.hChildStderrRdDup = win32api.DuplicateHandle(
            currentPid, self.hChildStderrRd, currentPid, 0, 0,
            win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStderrRd)
        self.hChildStderrRd = self.hChildStderrRdDup

        # Create a pipe for the child process's STDIN. This one is opened
        # in duplex mode so we can read from it too in order to detect when
        # the child closes their end of the pipe.
        self.stdinPipeName = r"\\.\pipe\twisted-iocp-stdin-%d-%d-%d" % (
            self.pid, counter.next(), time.time())
        self.hChildStdinWr = win32pipe.CreateNamedPipe(
            self.stdinPipeName,
            win32con.PIPE_ACCESS_DUPLEX
            | win32con.FILE_FLAG_OVERLAPPED,  # open mode
            win32con.PIPE_TYPE_BYTE,  # pipe mode
            1,  # max instances
            self.pipeBufferSize,  # out buffer size
            self.pipeBufferSize,  # in buffer size
            0,  # timeout 
            saAttr)

        self.hChildStdinRd = win32file.CreateFile(
            self.stdinPipeName, win32con.GENERIC_READ,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE, saAttr,
            win32con.OPEN_EXISTING, win32con.FILE_FLAG_OVERLAPPED, 0)

        # Duplicate the write handle to the pipe so it is not inherited.
        self.hChildStdinWrDup = win32api.DuplicateHandle(
            currentPid, self.hChildStdinWr, currentPid, 0, 0,
            win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStdinWr)
        self.hChildStdinWr = self.hChildStdinWrDup

        # set the info structure for the new process.  This is where
        # we tell the process to use the pipes for stdout/err/in.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = self.hChildStdoutWr
        StartupInfo.hStdError = self.hChildStderrWr
        StartupInfo.hStdInput = self.hChildStdinRd
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES

        # create the process
        cmdline = quoteArguments(args)
        self.hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(
            command,  # name
            cmdline,  # command line
            None,  # process security attributes
            None,  # primary thread security attributes
            1,  # handles are inherited
            0,  # creation flags
            environment,  # if NULL, use parent environment
            path,  # current directory
            StartupInfo)  # STARTUPINFO pointer

        # close handles which only the child will use
        win32file.CloseHandle(self.hChildStderrWr)
        win32file.CloseHandle(self.hChildStdoutWr)
        win32file.CloseHandle(self.hChildStdinRd)

        # Begin reading on stdout and stderr, before we have output on them.
        self.readOutOp.initiateOp(self.hChildStdoutRd, self.outBuffer)
        self.readErrOp.initiateOp(self.hChildStderrRd, self.errBuffer)
        # Read stdin which was opened in duplex mode so we can detect when
        # the child closed their end of the pipe.
        self.readInOp.initiateOp(self.hChildStdinWr, self.inBuffer)

        # When the process is done, call connectionLost().
        # This function returns right away.  Note I call this after
        # protocol.makeConnection to ensure that the protocol doesn't
        # have processEnded called before protocol.makeConnection.
        self.reactor.processWaiter.beginWait(self.reactor, self.hProcess, self)

        # notify protocol by calling protocol.makeConnection and specifying
        # ourself as the transport.
        self.protocol.makeConnection(self)
Example #14
0
    def __init__(self, reactor, protocol, command, args, environment, path):
        self.reactor = reactor
        self.protocol = protocol
        self.outBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        self.errBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        # This is the buffer for *reading* stdin, which is only done to
        # determine if the other end of the pipe was closed.
        self.inBuffer = reactor.AllocateReadBuffer(self.bufferSize)
        # IO operation classes
        self.readOutOp = ops.ReadOutOp(self)
        self.readErrOp = ops.ReadErrOp(self)
        self.readInOp = ops.ReadInOp(self)
        self.writeInOp = ops.WriteInOp(self)
        
        self.writeBuffer = ""
        self.writing = False
        self.finished = False
        self.offset = 0
        self.writeBufferedSize = 0
        self.closingStdin = False
        self.closedStdin = False
        self.closedStdout = False
        self.closedStderr = False
        # Stdio handles
        self.hChildStdinRd = None
        self.hChildStdinWr = None
        self.hChildStdinWrDup = None
        self.hChildStdoutRd = None
        self.hChildStdoutWr = None
        self.hChildStdoutRdDup = None
        self.hChildStderrRd = None
        self.hChildStderrWr = None
        self.hChildStderrRdDup = None
        
        self.closedNotifies = 0  # increments to 3 (for stdin, stdout, stderr)
        self.closed = False # set to true when all 3 handles close
        self.exited = False # set to true when WFMO thread gets signalled proc handle.  See doWaitForProcessExit.

        # Set the bInheritHandle flag so pipe handles are inherited. 
        saAttr = win32security.SECURITY_ATTRIBUTES()
        saAttr.bInheritHandle = 1
        
        currentPid = win32api.GetCurrentProcess() # -1 which stands for current process
        self.pid = os.getpid() # unique pid for pipe naming
        
        # Create a pipe for the child process's STDOUT. 
        self.stdoutPipeName = r"\\.\pipe\twisted-iocp-stdout-%d-%d-%d" % (self.pid, counter.next(), time.time())
        self.hChildStdoutRd = win32pipe.CreateNamedPipe(
                self.stdoutPipeName,
                win32con.PIPE_ACCESS_INBOUND | win32con.FILE_FLAG_OVERLAPPED, # open mode
                win32con.PIPE_TYPE_BYTE, # pipe mode
                1, # max instances
                self.pipeBufferSize, # out buffer size
                self.pipeBufferSize, # in buffer size
                0, # timeout 
                saAttr)

        self.hChildStdoutWr = win32file.CreateFile(
                self.stdoutPipeName,
                win32con.GENERIC_WRITE,
                win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE,
                saAttr,
                win32con.OPEN_EXISTING,
                win32con.FILE_FLAG_OVERLAPPED,
                0);
 
        # Create noninheritable read handle and close the inheritable read 
        # handle.
        self.hChildStdoutRdDup = win32api.DuplicateHandle(
                currentPid, self.hChildStdoutRd,
                currentPid, 0,
                0,
                win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStdoutRd);
        self.hChildStdoutRd = self.hChildStdoutRdDup
        
        # Create a pipe for the child process's STDERR.
        self.stderrPipeName = r"\\.\pipe\twisted-iocp-stderr-%d-%d-%d" % (self.pid, counter.next(), time.time())
        self.hChildStderrRd = win32pipe.CreateNamedPipe(
                self.stderrPipeName,
                win32con.PIPE_ACCESS_INBOUND | win32con.FILE_FLAG_OVERLAPPED, # open mode
                win32con.PIPE_TYPE_BYTE, # pipe mode
                1, # max instances
                self.pipeBufferSize, # out buffer size
                self.pipeBufferSize, # in buffer size
                0, # timeout 
                saAttr)
        self.hChildStderrWr = win32file.CreateFile(
                self.stderrPipeName,
                win32con.GENERIC_WRITE,
                win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE,
                saAttr,
                win32con.OPEN_EXISTING,
                win32con.FILE_FLAG_OVERLAPPED,
                0);

        # Create noninheritable read handle and close the inheritable read 
        # handle.
        self.hChildStderrRdDup = win32api.DuplicateHandle(
                currentPid, self.hChildStderrRd,
                currentPid, 0,
                0,
                win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStderrRd)
        self.hChildStderrRd = self.hChildStderrRdDup
        
        # Create a pipe for the child process's STDIN. This one is opened
        # in duplex mode so we can read from it too in order to detect when
        # the child closes their end of the pipe.
        self.stdinPipeName = r"\\.\pipe\twisted-iocp-stdin-%d-%d-%d" % (self.pid, counter.next(), time.time())
        self.hChildStdinWr = win32pipe.CreateNamedPipe(
                self.stdinPipeName,
                win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED, # open mode
                win32con.PIPE_TYPE_BYTE, # pipe mode
                1, # max instances
                self.pipeBufferSize, # out buffer size
                self.pipeBufferSize, # in buffer size
                0, # timeout 
                saAttr)

        self.hChildStdinRd = win32file.CreateFile(
                self.stdinPipeName,
                win32con.GENERIC_READ,
                win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE,
                saAttr,
                win32con.OPEN_EXISTING,
                win32con.FILE_FLAG_OVERLAPPED,
                0);
        
        # Duplicate the write handle to the pipe so it is not inherited.
        self.hChildStdinWrDup = win32api.DuplicateHandle(
                currentPid, self.hChildStdinWr, 
                currentPid, 0, 
                0,
                win32con.DUPLICATE_SAME_ACCESS)
        win32api.CloseHandle(self.hChildStdinWr)
        self.hChildStdinWr = self.hChildStdinWrDup
        
        # set the info structure for the new process.  This is where
        # we tell the process to use the pipes for stdout/err/in.
        StartupInfo = win32process.STARTUPINFO()
        StartupInfo.hStdOutput = self.hChildStdoutWr
        StartupInfo.hStdError  = self.hChildStderrWr
        StartupInfo.hStdInput  = self.hChildStdinRd
        StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES
        
        # create the process
        cmdline = quoteArguments(args)
        self.hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(
                command,     # name
                cmdline,     # command line
                None,        # process security attributes
                None,        # primary thread security attributes
                1,           # handles are inherited
                0,           # creation flags
                environment, # if NULL, use parent environment
                path,        # current directory
                StartupInfo) # STARTUPINFO pointer 

        # close handles which only the child will use
        win32file.CloseHandle(self.hChildStderrWr)
        win32file.CloseHandle(self.hChildStdoutWr)
        win32file.CloseHandle(self.hChildStdinRd)
        
        # Begin reading on stdout and stderr, before we have output on them.
        self.readOutOp.initiateOp(self.hChildStdoutRd, self.outBuffer)
        self.readErrOp.initiateOp(self.hChildStderrRd, self.errBuffer)
        # Read stdin which was opened in duplex mode so we can detect when
        # the child closed their end of the pipe.
        self.readInOp.initiateOp(self.hChildStdinWr, self.inBuffer)

        # When the process is done, call connectionLost().
        # This function returns right away.  Note I call this after
        # protocol.makeConnection to ensure that the protocol doesn't
        # have processEnded called before protocol.makeConnection.
        self.reactor.processWaiter.beginWait(self.reactor, self.hProcess, self)
        
        # notify protocol by calling protocol.makeConnection and specifying
        # ourself as the transport.
        self.protocol.makeConnection(self)