예제 #1
0
            def process_dict_input(dictionary):

                # vars.
                expect = list(dictionary.keys())
                send = list(dictionary.values())

                # expect .
                if log_level >= 8:
                    print(f"Expecting one of the following inputs: {expect}.")
                response = spawn.expect(expect=expect,
                                        send=send,
                                        timeout=timeout)
                if not response.success:
                    if "None of the specified inputs were expected." in response.error:
                        if optional:
                            return Response.error(
                                f"Unable to find the expected input but still success since it is optional."
                            )
                        else:
                            return Response.error(
                                f"Specified input [{Array(expect).string(joiner=', ')}] was not expected."
                            )
                    else:
                        return response
                if log_level >= 8:
                    print("Send response message:", response.message)

                # success.
                return Response.success("Success.")
예제 #2
0
	def send_crash(self, 
		# all optional.
		# option 1: the success message.
		message=None, # (1)
		args={}, # (2)
		# option 2: the error message.
		error=None,
		# option 3: the response object.
		response=None, 
		# save the message/error/response.
		save=False,
		# the active log level (int) (leave None to use self.log_level).
		log_level=None,
		# the required log level for when to print to console (leave None to use Response.log_level ; default: 0).
		required_log_level=Response.log_level,
	):
		if log_level == None: log_level = self.log_level
		if isinstance(message, (str,String)):
			self.__response__ = Response.success(message, args, log_level=-1, save=False)
			msg = message
		elif isinstance(error, (str,String)):
			self.__response__ = Response.error(error, log_level=-1, save=False)
			msg = error
		elif isinstance(response, ResponseObject):
			self.__response__ = response
			if response["success"]:
				msg = response["message"]
			else:
				msg = response["error"]
		else:
			raise Exceptions.InvalidUsage("Define one of the following parameters: [message:str, error:str, response:ResponseObject].")
		self.__status__ = "crashed"
		if log_level >= required_log_level or save:
			Response.log(response=self.__response__, save=save, log_level=log_level, required_log_level=required_log_level)
		return self.__response__
예제 #3
0
 def crashed(self):
     response = self.read(wait=False)
     if not response.success: return response
     if self.exit_status not in [0, None]:
         return Response.error(
             f"{self.response_str} returned exit status: [{self.exit_status}] (output: {self.read(wait=False, __safe__=True).output})."
         )
     return Response.success(f"{self.response_str} is not crashed.")
예제 #4
0
	def safe_start(self, timeout=120, sleeptime=1):
		self.log(f"Stopping thread {self.id}.")
		self.start()
		for i in range(int(timeout/sleeptime)):
			if self.running: break
			time.sleep(sleeptime)
		if not self.running: 
			return Response.error(f"Unable to start thread {self}.", log_level=self.log_level, required_log_level=0)
		return Response.success(f"Successfully started thread {self.id}.", log_level=self.log_level, required_log_level=0)
예제 #5
0
    def kill(self):

        # handle output.
        killed = None
        try:
            #if self.async_:
            #	g = yield from self.child.terminate(force=True, async_=True)
            #	killed = next(x)
            #else:
            killed = self.child.terminate(force=True)
        except Exception as e:
            return Response.error(
                f"Failed to kill process [{self.command}], error: {e}.")
        if killed == None:
            return Response.error(
                f"Failed to kill process [{self.command}] (#452983).")
        if not killed:
            return Response.error(f"Unable to kill process [{self.command}].")
        else:
            return Response.success(
                f"Successfully killed process [{self.command}].")
예제 #6
0
 def start(self):
     try:
         self.child = pexpect.spawn(self.command)
     except Exception as e:
         return Response.error(
             f"Failed to spawn {self.response_str}, error: {e}.")
     # check exit status.
     if self.child.exitstatus not in [0, None]:
         return OutputObject(
             error=
             f"{self.response_str} returned exit status: [{spawn.child.exitstatus}] (output: {self.read(wait=False, __safe__=True).output})."
         )
     self.__output__ = ""
     return Response.success(f"Successfully spawned {self.response_str}.")
예제 #7
0
	def safe_stop(self, timeout=120, sleeptime=1):
		self.log(f"Stopping thread {self.id}.")
		self.send_stop()
		for i in range(int(timeout/sleeptime)):
			if self.stopped: break
			time.sleep(sleeptime)
		if not self.stopped: 
			return Response.error(f"Unable to stop thread {self}.")
		found = False
		try:
			response = self.stop()
			found = True
		except AttributeError: response = None
		if not found:
			try:
				response = self.__stop__()
				found = True
			except AttributeError: response = None
		if isinstance(response, ResponseObject) and not response.success:
			return response
		return Response.success(f"Successfully stopped thread {self.id}.", required_log_level=0)
예제 #8
0
    def expect(
        self,
        # the expected data parameter (#1).
        #	str instantce: expect a single identifier.
        #	list instance: expect one of the provided identifiers & return the found one if success.
        expect=["Password*"],
        # the optional data to send (#2).
        #	none instance: do not send anything.
        #	str instance: the data to send.
        #	list/tuple instance: send value of index from expected expect (required expect to be a list, Array & the indexes of [expect, send] be match).
        send=None,
        # the timeout (float).
        timeout=1.0,
    ):
        # check none timeout.
        if timeout == None: timeout = 1.0

        # single expect.
        if isinstance(expect, str):
            if isinstance(send, (list, Array)):
                raise Exceptions.InvalidUsage(
                    f"{self.__traceback__(function='expect', parameter='send')}: parameter [send] requires to be be a [str, String] when parameter [expect] is a [{expect.__class__.__name__}], not [{send.__class__.__name__}]."
                )
            """ add to lines to output (before) (adds nothing when empty) (do not use self.expecting before adding the output). """
            response = self.read(wait=False)
            if not response.success: return response
            """ check expect & send if provided. """
            c = 1
            try:
                #if self.async_:
                #	g = yield from self.child.expect(expect, timeout=timeout, async_=True)
                #	r = next(g)
                #else:
                r = self.child.expect(expect, timeout=timeout)
                if not isinstance(r, (int, Integer, float)):
                    return Response.error(
                        f"Expected [{expect}] is not the child's expected input (#873465)."
                    )
                c = 2
                if self.log_level >= 8: print(f"Found expected: {expect}")
                if send != None:
                    if self.log_level >= 8:
                        print(f"Attempting to send: {send}")
                    #if self.async_:
                    #	g = yield from self.child.sendline(str(send), async_=True)
                    #	r = next(g)
                    #else:
                    r = self.child.sendline(str(send))
                    self.__secrets__.append(str(send))
                    if self.log_level >= 8:
                        print(f"Succesfully sended: {send}")
            except pexpect.exceptions.TIMEOUT:
                if c == 1:
                    return Response.error(
                        f"Expected [{expect}] is not the child's expected input, error: Timeout (during epxecting)."
                    )
                else:
                    return Response.error(
                        f"Failed to send expected [{expect}], error: Timeout (during sending input)."
                    )
            except pexpect.exceptions.EOF:
                if c == 1:
                    return Response.error(
                        f"Expected [{expect}] is not the child's expected input, error: End of file (during epxecting)."
                    )
                else:
                    return Response.error(
                        f"Failed to send expected [{expect}], error: End of file (during sending input)."
                    )
            except Exception as e:
                if c == 1:
                    return Response.error(
                        f"Expected [{expect}] is not the child's expected input, error: {e}."
                    )
                else:
                    return Response.error(
                        f"Failed to send expected [{expect}], error: {e}.")
            """ add to lines to output (after) (adds nothing when empty) (do not use self.expecting before adding the output). """
            response = self.read(wait=False)
            if not response.success: return response

            # handler.
            if send != None:
                return Response.success(
                    f"Successfully send expected input ({expect}).")
            else:
                return Response.success(
                    f"Successfully retrieved expected input ({expect}).")

        # list expect.
        elif isinstance(expect, (list, Array)):
            index = 0
            for _expect_ in expect:
                if isinstance(send, (list, Array)):
                    try:
                        _send_ = str(send[index])
                    except:
                        raise Exceptions.InvalidUsage(
                            f"{self.__traceback__(function='expect', parameter='send')}: parameter [send] and parameter [expect] do not have the same indexes."
                        )
                else:
                    _send_ = str(send)
                if self.log_level >= 8:
                    print(f"Checking optional expect: {_expect_}")
                response = self.expect(expect=_expect_,
                                       timeout=timeout,
                                       send=_send_)
                if not response.success and "is not the child's expected input" not in response.error:
                    return response
                elif response.success:
                    return Response.success(
                        f"Successfully {Boolean(send).string(true='send', false='retrieved')} the expected input(s).",
                        {
                            "expected": _expect_,
                            "index": index,
                        })
                index += 1
            return Response.error(f"None of the specified input was expected.")

        # invalid usage.
        else:
            raise Exceptions.InvalidUsage(
                f"{self.__traceback__(function='expect', parameter='expect')}: parameter [expect] requires to be be a [Dictionary], not [{config.__class__.__name__}]."
            )
예제 #9
0
    def read(
        self,
        # with await False it reads only the printed output regardless the status & never throws timeout.
        wait=False,
        # the timeout, leave None for no timeout.
        timeout=None,
        # the live boolean (bool) (prints live logs to console when enabled) (leave None to use self.log_level >= 1).
        live=None,
        # system variables.
        #   safe True always a response.output variable upon error the response.output is "".
        __safe__=False,
    ):

        # clean line.
        def clean_line(line):
            if isinstance(line, bytes): line = line.decode()
            if line in [" password:"******"", " ", "  ", "   ", "    "
                    ] and len(line) >= len(strip_last) and line[
                            -len(strip_last):] == strip_last:
                        return line[:-len(strip_last)]
            return line

        def clean_output(output):
            _output_, b = "", output.replace("\r", "").replace("\t",
                                                               "").split("\n")
            c, m = 0, len(b) - 1
            for line in b:
                l = clean_line(line)
                if l not in [None]:
                    if c < m: _output_ += l + "\n"
                    else: _output_ += l
                c += 1
            return _output_

        def log_output(output):
            while True:
                if len(output) >= 1 and output[len(output) - 1] == "\n":
                    output = output[:-1]
                else:
                    break
            print(output)

        # checks.
        if live == None: live = self.log_level >= 1

        # old timeout.
        old = self.child.timeout

        # version 2: reads only the printed lines and stops when the timeout is hit so there is no timeout required.
        output_logs_allowed = True
        if not wait:
            self.child.timeout = 0.25
            output_logs_allowed = False
            output, c = "", 0
            for line in range(1000000000):
                try:
                    #if self.async_:
                    #	g = yield from self.child.readline(line, async_=True)
                    #	output += next(g).decode()
                    #else:
                    new = self.child.readline(line).decode()
                    if new == "":
                        c += 1
                        if c >= 100: break
                    else:
                        output_logs_allowed = True
                        c = 0
                        output += new
                except pexpect.exceptions.TIMEOUT:
                    break
                except pexpect.exceptions.EOF:
                    break
                except Exception as e:
                    if timeout != None: self.child.timeout = old
                    e = str(e)
                    if self.log_level <= 0:
                        e = str(e).split(
                            "\n"
                        )[0]  # strip the full child from the pexpect error message.
                    while True:
                        if len(e) >= 1 and e[len(e) - 1] == ".": e = e[:-1]
                        else: break
                    if "Timeout" in str(e):
                        response = Response.error(
                            f"{e} (most likely the command is still expecting input)."
                        )
                        if __safe__: response.output = ""
                        return response
                    else:
                        response = Response.error(f"{e}.")
                        if __safe__: response.output = ""
                        return response

        # version 1: throws an error when unable to read output if timeout is defined, so it can be used to detect if input is expected.
        else:

            # handle output.
            self.child.timeout = timeout
            try:
                #output = self.child.read().decode()
                output = ""
                #if self.async_:
                #	g = yield from self.child.readlines(async_=True)
                #	lines = next(x)
                #else:
                lines = self.child.readlines()
                if lines == []:
                    output_logs_allowed = False
                else:
                    for i in lines:
                        output += i.decode()
            except Exception as e:
                self.child.timeout = old
                e = str(e)
                if self.log_level <= 0:
                    e = str(e).split(
                        "\n"
                    )[0]  # strip the full child from the pexpect error message.
                while True:
                    if len(e) >= 1 and e[len(e) - 1] == ".": e = e[:-1]
                    else: break
                if "Timeout" in str(e):
                    response = Response.error(
                        f"{e} (most likely the command is still expecting input)."
                    )
                    if __safe__: response.output = ""
                    return response
                else:
                    response = Response.error(f"{e}.")
                    if __safe__: response.output = ""
                    return response

        # clean output.
        output = clean_output(output)
        if output_logs_allowed and live: log_output(output)

        # handler.
        self.child.timeout = old
        self.__output__ += output
        self.__output__ = clean_output(self.__output__)
        return Response.success("Successfully retrieved the child's output.", {
            "output": str(self.__output__),
            "new_output": output,
        })