# Copyright (c) 2015 Michel Oosterhof <michel@oosterhof.net>
# All rights reserved.

"""
This module contains the python commnad
"""

from __future__ import annotations


import getopt

from twisted.python import log

from cowrie.shell.command import HoneyPotCommand

commands = {}


class Command_python(HoneyPotCommand):
    def version(self) -> None:
        ver = "Python 2.7.11+"
        self.write(ver + "\n")

    def help(self) -> None:
        output = (
            "usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...",
            "Options and arguments (and corresponding environment variables):",
            "-B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x",
            "-c cmd : program passed in as string (terminates option list)",
            "-d     : debug output from parser; also PYTHONDEBUG=x",
            "-E     : ignore PYTHON* environment variables (such as PYTHONPATH)",
            "-h     : print this help message and exit (also --help)",
            "-i     : inspect interactively after running script; forces a prompt even",
            "         if stdin does not appear to be a terminal; also PYTHONINSPECT=x",
            "-m mod : run library module as a script (terminates option list)",
            "-O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x",
            "-OO    : remove doc-strings in addition to the -O optimizations",
            "-R     : use a pseudo-random salt to make hash() values of various types be",
            "         unpredictable between separate invocations of the interpreter, as",
            "         a defense against denial-of-service attacks",
            "-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew",
            "-s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE",
            "-S     : don't imply 'import site' on initialization",
            "-t     : issue warnings about inconsistent tab usage (-tt: issue errors)",
            "-u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x",
            "         see man page for details on internal buffering relating to '-u'",
            "-v     : verbose (trace import statements); also PYTHONVERBOSE=x",
            "         can be supplied multiple times to increase verbosity",
            "-V     : print the Python version number and exit (also --version)",
            "-W arg : warning control; arg is action:message:category:module:lineno",
            "         also PYTHONWARNINGS=arg",
            "-x     : skip first line of source, allowing use of non-Unix forms of #!cmd",
            "-3     : warn about Python 3.x incompatibilities that 2to3 cannot trivially fix",
            "file   : program read from script file",
            "-      : program read from stdin (default; interactive mode if a tty)",
            "arg ...: arguments passed to program in sys.argv[1:]",
            "",
            "Other environment variables:",
            "PYTHONSTARTUP: file executed on interactive startup (no default)",
            "PYTHONPATH   : ':'-separated list of directories prefixed to the",
            "               default module search path.  The result is sys.path.",
            "PYTHONHOME   : alternate <prefix> directory (or <prefix>:<exec_prefix>).",
            "               The default module search path uses <prefix>/pythonX.X.",
            "PYTHONCASEOK : ignore case in 'import' statements (Windows).",
            "PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.",
            "PYTHONHASHSEED: if this variable is set to 'random', the effect is the same",
            "   as specifying the -R option: a random value is used to seed the hashes of",
            "   str, bytes and datetime objects.  It can also be set to an integer",
            "   in the range [0,4294967295] to get hash values with a predictable seed.",
        )
        for line in output:
            self.write(line + "\n")

    def start(self) -> None:
        try:
            opts, args = getopt.gnu_getopt(
                self.args, "BdEhiORsStuvVx3c:m:Q:W:", ["help", "version"]
            )
        except getopt.GetoptError as err:
            self.write(f"Unknown option: -{err.opt}\n")
            self.write(
                "usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ... \n"
            )
            self.write("Try `python -h' for more information.\n")
            self.exit()
            return

        # Parse options
        for o, _a in opts:
            if o in "-V":
                self.version()
                self.exit()
                return
            elif o in "--help":
                self.help()
                self.exit()
                return
            elif o in "-h":
                self.help()
                self.exit()
                return
            elif o in "--version":
                self.version()
                self.exit()
                return

        for value in args:
            sourcefile = self.fs.resolve_path(value, self.protocol.cwd)

            if self.fs.exists(sourcefile) or value == "-":
                self.exit()
            else:
                self.write(
                    f"python: can't open file '{value}': [Errno 2] No such file or directory\n"
                )
                self.exit()

        if not len(self.args):
            pass

    def lineReceived(self, line: str) -> None:
        log.msg(
            eventid="cowrie.command.input",
            realm="python",
            input=line,
            format="INPUT (%(realm)s): %(input)s",
        )

    def handle_CTRL_D(self) -> None:
        self.exit()


commands["/usr/bin/python"] = Command_python
commands["python"] = Command_python
