Esempio n. 1
0
 def setBuilddir(self, builddir):
     assert self.parent
     self.builddir = builddir
     self.basedir = os.path.join(bytes2NativeString(self.bot.basedir),
                                 bytes2NativeString(self.builddir))
     if not os.path.isdir(self.basedir):
         os.makedirs(self.basedir)
Esempio n. 2
0
 def setBuilddir(self, builddir):
     assert self.parent
     self.builddir = builddir
     self.basedir = os.path.join(bytes2NativeString(self.bot.basedir),
                                 bytes2NativeString(self.builddir))
     if not os.path.isdir(self.basedir):
         os.makedirs(self.basedir)
Esempio n. 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('%', '%%')
Esempio n. 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(mode='w+', dir='.', suffix=".bat",
                                delete=False)
        # echo off hides this cheat from the log files.
        tf.write("@echo off\n")
        if isinstance(self.command, (string_types, bytes)):
            tf.write(bytes2NativeString(self.command))
        else:
            tf.write(win32_batch_quote(self.command))
        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)
Esempio n. 5
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('%', '%%')
Esempio n. 6
0
 def _collapseMsg(self, msg):
     """
     Take msg, which is a dictionary of lists of output chunks, and
     concatenate all the chunks into a single string
     """
     retval = {}
     for logname in msg:
         data = ""
         for m in msg[logname]:
             m = bytes2NativeString(m, self.builder.unicode_encoding)
             data += m
         if isinstance(logname, tuple) and logname[0] == 'log':
             retval['log'] = (logname[1], data)
         else:
             retval[logname] = data
     return retval
Esempio n. 7
0
 def _collapseMsg(self, msg):
     """
     Take msg, which is a dictionary of lists of output chunks, and
     concatenate all the chunks into a single string
     """
     retval = {}
     for logname in msg:
         data = ""
         for m in msg[logname]:
             m = bytes2NativeString(m, self.builder.unicode_encoding)
             data += m
         if isinstance(logname, tuple) and logname[0] == 'log':
             retval['log'] = (logname[1], data)
         else:
             retval[logname] = data
     return retval
Esempio n. 8
0
def shell_quote(cmd_list, unicode_encoding='utf-8'):
    # attempt to quote cmd_list such that a shell will properly re-interpret
    # it.  The pipes module is only available on UNIX; also, the quote
    # function is undocumented (although it looks like it will be documented
    # soon: http://bugs.python.org/issue9723). Finally, it has a nasty bug
    # in some versions where an empty string is not quoted.
    #
    # So:
    #  - use pipes.quote on UNIX, handling '' as a special case
    #  - use our own custom function on Windows
    cmd_list = bytes2NativeString(cmd_list, unicode_encoding)

    if runtime.platformType == 'win32':
        return win32_batch_quote(cmd_list, unicode_encoding)

    import pipes  # only available on unix

    def quote(e):
        if not e:
            return '""'
        e = bytes2NativeString(e, unicode_encoding)
        return pipes.quote(e)
    return " ".join([quote(e) for e in cmd_list])
Esempio n. 9
0
 def quote(e):
     if not e:
         return '""'
     e = bytes2NativeString(e, unicode_encoding)
     return pipes.quote(e)
Esempio n. 10
0
    def _startCommand(self):
        # ensure workdir exists
        if not os.path.isdir(self.workdir):
            os.makedirs(self.workdir)
        log.msg("RunProcess._startCommand")
        if self.notreally:
            self._addToBuffers(
                'header',
                "command '%s' in dir %s" % (self.fake_command, self.workdir))
            self._addToBuffers('header', "(not really)\n")
            self.finished(None, 0)
            return

        self.pp = RunProcessPP(self)

        self.using_comspec = False
        if isinstance(self.command, bytes):
            if runtime.platformType == 'win32':
                # allow %COMSPEC% to have args
                argv = os.environ['COMSPEC'].split()
                if '/c' not in argv:
                    argv += ['/c']
                argv += [self.command]
                self.using_comspec = True
            else:
                # for posix, use /bin/sh. for other non-posix, well, doesn't
                # hurt to try
                argv = [b'/bin/sh', b'-c', self.command]
            display = self.fake_command
        else:
            # On windows, CreateProcess requires an absolute path to the executable.
            # When we call spawnProcess below, we pass argv[0] as the executable.
            # So, for .exe's that we have absolute paths to, we can call directly
            # Otherwise, we should run under COMSPEC (usually cmd.exe) to
            # handle path searching, etc.
            if runtime.platformType == 'win32' and not \
                    (self.command[0].lower().endswith(".exe") and os.path.isabs(self.command[0])):
                # allow %COMSPEC% to have args
                argv = os.environ['COMSPEC'].split()
                if '/c' not in argv:
                    argv += ['/c']
                argv += list(self.command)
                self.using_comspec = True
            else:
                argv = self.command
            # Attempt to format this for use by a shell, although the process
            # isn't perfect
            display = shell_quote(self.fake_command,
                                  self.builder.unicode_encoding)

        display = bytes2NativeString(display, self.builder.unicode_encoding)

        # $PWD usually indicates the current directory; spawnProcess may not
        # update this value, though, so we set it explicitly here.  This causes
        # weird problems (bug #456) on msys, though..
        if not self.environ.get('MACHTYPE', None) == 'i686-pc-msys':
            self.environ['PWD'] = os.path.abspath(self.workdir)

        # self.stdin is handled in RunProcessPP.connectionMade

        log.msg(" " + display)
        self._addToBuffers('header', display + "\n")

        # then comes the secondary information
        msg = " in dir %s" % (self.workdir, )
        if self.timeout:
            if self.timeout == 1:
                unit = "sec"
            else:
                unit = "secs"
            msg += " (timeout %d %s)" % (self.timeout, unit)
        if self.maxTime:
            if self.maxTime == 1:
                unit = "sec"
            else:
                unit = "secs"
            msg += " (maxTime %d %s)" % (self.maxTime, unit)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        msg = " watching logfiles %s" % (self.logfiles, )
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # then the obfuscated command array for resolving unambiguity
        msg = " argv: %s" % (self.fake_command, )
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # then the environment, since it sometimes causes problems
        if self.logEnviron:
            msg = " environment:\n"
            env_names = sorted(self.environ.keys())
            for name in env_names:
                msg += "  %s=%s\n" % (name, self.environ[name])
            log.msg(" environment:\n%s" % (pprint.pformat(self.environ), ))
            self._addToBuffers('header', msg)

        if self.initialStdin:
            msg = " writing %d bytes to stdin" % len(self.initialStdin)
            log.msg(" " + msg)
            self._addToBuffers('header', msg + "\n")

        msg = " using PTY: %s" % bool(self.usePTY)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # put data into stdin and close it, if necessary.  This will be
        # buffered until connectionMade is called
        if self.initialStdin:
            self.pp.setStdin(self.initialStdin)

        self.startTime = util.now(self._reactor)

        # start the process

        self.process = self._spawnProcess(self.pp,
                                          argv[0],
                                          argv,
                                          self.environ,
                                          self.workdir,
                                          usePTY=self.usePTY)

        # set up timeouts

        if self.timeout:
            self.ioTimeoutTimer = self._reactor.callLater(
                self.timeout, self.doTimeout)

        if self.maxTime:
            self.maxTimeoutTimer = self._reactor.callLater(
                self.maxTime, self.doMaxTimeout)

        for w in self.logFileWatchers:
            w.start()
Esempio n. 11
0
 def errReceived(self, data):
     if self.debug:
         log.msg("RunProcessPP.errReceived")
     data = bytes2NativeString(data, self.command.builder.unicode_encoding)
     self.command.addStderr(data)
Esempio n. 12
0
 def quote(e):
     if not e:
         return '""'
     e = bytes2NativeString(e, unicode_encoding)
     return pipes.quote(e)
Esempio n. 13
0
    def _startCommand(self):
        # ensure workdir exists
        if not os.path.isdir(self.workdir):
            os.makedirs(self.workdir)
        log.msg("RunProcess._startCommand")
        if self.notreally:
            self._addToBuffers('header', "command '%s' in dir %s" %
                               (self.fake_command, self.workdir))
            self._addToBuffers('header', "(not really)\n")
            self.finished(None, 0)
            return

        self.pp = RunProcessPP(self)

        self.using_comspec = False
        if isinstance(self.command, bytes):
            if runtime.platformType == 'win32':
                # allow %COMSPEC% to have args
                argv = os.environ['COMSPEC'].split()
                if '/c' not in argv:
                    argv += ['/c']
                argv += [self.command]
                self.using_comspec = True
            else:
                # for posix, use /bin/sh. for other non-posix, well, doesn't
                # hurt to try
                argv = [b'/bin/sh', b'-c', self.command]
            display = self.fake_command
        else:
            # On windows, CreateProcess requires an absolute path to the executable.
            # When we call spawnProcess below, we pass argv[0] as the executable.
            # So, for .exe's that we have absolute paths to, we can call directly
            # Otherwise, we should run under COMSPEC (usually cmd.exe) to
            # handle path searching, etc.
            if (runtime.platformType == 'win32' and
                not (bytes2NativeString(self.command[0]).lower().endswith(".exe") and
                     os.path.isabs(self.command[0]))):
                # allow %COMSPEC% to have args
                argv = os.environ['COMSPEC'].split()
                if '/c' not in argv:
                    argv += ['/c']
                argv += list(self.command)
                self.using_comspec = True
            else:
                argv = self.command
            # Attempt to format this for use by a shell, although the process
            # isn't perfect
            display = shell_quote(self.fake_command, self.builder.unicode_encoding)

        display = bytes2NativeString(display, self.builder.unicode_encoding)

        # $PWD usually indicates the current directory; spawnProcess may not
        # update this value, though, so we set it explicitly here.  This causes
        # weird problems (bug #456) on msys, though..
        if not self.environ.get('MACHTYPE', None) == 'i686-pc-msys':
            self.environ['PWD'] = os.path.abspath(self.workdir)

        # self.stdin is handled in RunProcessPP.connectionMade

        log.msg(" " + display)
        self._addToBuffers('header', display + "\n")

        # then comes the secondary information
        msg = " in dir %s" % (self.workdir,)
        if self.timeout:
            if self.timeout == 1:
                unit = "sec"
            else:
                unit = "secs"
            msg += " (timeout %d %s)" % (self.timeout, unit)
        if self.maxTime:
            if self.maxTime == 1:
                unit = "sec"
            else:
                unit = "secs"
            msg += " (maxTime %d %s)" % (self.maxTime, unit)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        msg = " watching logfiles %s" % (self.logfiles,)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # then the obfuscated command array for resolving unambiguity
        msg = " argv: %s" % (self.fake_command,)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # then the environment, since it sometimes causes problems
        if self.logEnviron:
            msg = " environment:\n"
            env_names = sorted(self.environ.keys())
            for name in env_names:
                msg += "  %s=%s\n" % (name, self.environ[name])
            log.msg(" environment:\n%s" % (pprint.pformat(self.environ),))
            self._addToBuffers('header', msg)

        if self.initialStdin:
            msg = " writing %d bytes to stdin" % len(self.initialStdin)
            log.msg(" " + msg)
            self._addToBuffers('header', msg + "\n")

        msg = " using PTY: %s" % bool(self.usePTY)
        log.msg(" " + msg)
        self._addToBuffers('header', msg + "\n")

        # put data into stdin and close it, if necessary.  This will be
        # buffered until connectionMade is called
        if self.initialStdin:
            self.pp.setStdin(self.initialStdin)

        self.startTime = util.now(self._reactor)

        # start the process

        self.process = self._spawnProcess(
            self.pp, argv[0], argv,
            self.environ,
            self.workdir,
            usePTY=self.usePTY)

        # set up timeouts

        if self.timeout:
            self.ioTimeoutTimer = self._reactor.callLater(
                self.timeout, self.doTimeout)

        if self.maxTime:
            self.maxTimeoutTimer = self._reactor.callLater(
                self.maxTime, self.doMaxTimeout)

        for w in self.logFileWatchers:
            w.start()
Esempio n. 14
0
 def errReceived(self, data):
     if self.debug:
         log.msg("RunProcessPP.errReceived")
     data = bytes2NativeString(
         data, self.command.builder.unicode_encoding)
     self.command.addStderr(data)