Example #1
0
def main():
    """
    Initialize everything and launch NakedSun. This method is in charge of
    parsing command line arguments, locating the MUD library, loading all the
    available modules, loading the world, etc.
    """

    ## Argument Parsing

    parser = argparse.ArgumentParser(
                prog="python -m nakedsun",
                description=nakedsun.__doc__,
                version="NakedSun %s" % nakedsun.version
                )

    # Basic Options

    parser.add_argument("--path", dest="lib", default="lib", metavar="PATH",
                        help="Load the MUD library from PATH.")
    parser.add_argument("--copyover", help=argparse.SUPPRESS)

    # Network Options
    group = parser.add_argument_group(
                u"Network Options",
                u"These options allow you to override the default listening "
                u"addresses for the server."
                )

    group.add_argument("-b", "--bind", dest="addr", default=None,
                    help=u"Bind the telnet server to the given ADDRESS:PORT.")
    group.add_argument("--http", dest="http_addr", default=None,
                    help=u"Bind the HTTP server to the given ADDRESS:PORT.")

    # Logging Options

    group = parser.add_argument_group(u"Logging Options")

    group.add_argument("-l", "--log", default="../log", metavar="PATH",
        help=u"Store log files at PATH, relative to the MUD library.")
    group.add_argument("--level", default="INFO",
        help=u"Only log messages of LEVEL or higher. (Default: INFO)")
    group.add_argument("--no-color", default=True, action="store_false",
        dest="color", help=u"Disable console output colorization.")

    # UID/GID Manipulation

    if do_uid:
        group = parser.add_argument_group(
            u"User/Group ID Manipulation",
            u"These options, if used, will be acted upon *immediately* before "
            u"entering the main event loop. This is slightly unsafe, since "
            u"any code in the MUD library will be executed before the new "
            u"user and/or group identity is assumed. However, this is "
            u"necessary to ensure the server is able to bind low ports on UNIX"
            u" systems as root. The provided values may be either names "
            u"or numbers. These values may also be set in the MUD's "
            u"configuration file.")

        group.add_argument("-u", "--uid", help=u"Run as the specified user.")
        group.add_argument("-g", "--gid",
            help=u"Run as the specified group.")
        group.add_argument("--umask", help=u"Use the provided umask.")
        group.add_argument("--early", default=False, action="store_true",
            help=u"Assume the new identity early, before executing any code "
                 u"from the MUD library.")

    # Finally, parse the arguments.
    args = parser.parse_args()

    ## Logging

    log.initialize(args.color, args.level, os.path.join(args.lib, args.log))
    log.naked(u"NakedSun v%s by Stendec <*****@*****.**>" % nakedsun.version)

    ## Enter the MUD Library

    path = os.path.realpath(args.lib)
    if not os.path.exists(path) or not (
            os.path.exists(os.path.join(path, 'muddata')) or
            os.path.exists(os.path.join(path, 'config'))):
        log.error(u"Cannot find the MUD library at: %s" % path)
        log.shutdown()
        sys.exit(1)

    if path != os.getcwd():
        log.info(u"Changing working directory to: %s" % path)
        os.chdir(path)

    ## Load Configuration

    log.info(u"Loading MUD configuration from file.")
    nakedsun.settings.initialize()

    ## Networking Initialization

    log.info(u"Initializing the network.")

    from . import network
    network.initialize(args.addr, args.http_addr)

    ## Early UID/GID Manipulation

    if do_uid and args.early:
        assume_uid(args.uid, args.gid, args.umask)

    ## NakedMud Compatibility

    if nakedsun.settings.get("nakedmud_compatible"):
        log.info("Loading NakedMud Compatibility Layer.")
        from . import nmcompat

    # Inject a series of modules into sys.modules for NakedMud compatibility.
    log.info(u"Injecting global modules for NakedMud compatibility.")
    for module in ("account", "auxiliary", "bitvectors", "char", "event",
                   "hooks", "mudsock", "mud", "mudsys", "obj", "room",
                   "storage"):
        inject(module, getattr(nakedsun, module))

    ## MUD Library Initialization

    log.info(u"Loading the MUD library.")

    # If it doesn't exist, die.
    if not os.path.exists("pymodules"):
        log.error(u"Cannot find pymodules in the MUD library.")
        log.shutdown()
        sys.exit(1)

    # Either load pymodules as a module or load its contents.
    if os.path.exists(os.path.join("pymodules", "__init__.py")):
        log.debug("Importing module: pymodules")
        import pymodules

    else:
        log.debug("pymodules is not a package. Entering directory.")
        path = os.path.abspath("pymodules")
        sys.path.insert(0, path)

        # Scan through.
        for fn in sorted(os.listdir("pymodules")):
            full = os.path.join(path, fn)

            # Skip hidden entries, non-.py files, and folders that aren't
            # python packages.
            if fn.startswith(".") or (os.path.isfile(full) and not
                    fn.endswith(".py")) or (os.path.isdir(full) and not
                    os.path.exists(os.path.join(full, "__init__.py"))):
                continue

            # If it's a file, trim off the end.
            if fn.endswith(".py"):
                fn = fn[:-3]

            # Log a message, and then load the module.
            log.debug("Importing module: %s" % fn)

            try:
                nakedsun.mudsys.pymodules[fn] = __import__(fn)
            except Exception:
                log.exception("An error occurred when attempting to import "
                              "Python module: %s (%s)" % (fn, full))
                log.shutdown()
                sys.exit(1)

    ## Copyover Recovery

    log.todo("Copyover Recovery.")

    ## Register Signals

    if hasattr(signal, 'SIGHUP'):
        signal.signal(signal.SIGHUP, signal_HUP)

    ## Late UID/GID Manipulation

    if do_uid and not args.early:
        assume_uid(args.uid, args.gid, args.umask)

    ## The Event Loop

    log.info(u"Entering the game loop.")
    log.line()

    begin_copyover = False

    try:
        pants.engine.start()
    except nakedsun.mudsys.SystemCopyover:
        begin_copyover = True
    except SystemExit:
        pass
    except KeyboardInterrupt:
        print ''

    log.line()

    if begin_copyover:
        log.todo("Copyover.")

    ## Cleanup

    nakedsun.hooks.run("shutdown")

    log.info(u"Exiting normally.")
    log.shutdown()
    sys.exit(0)
Example #2
0
def inject(name, module):
    """
    Inject a module into sys.modules with the given name.
    """
    log.debug("Injecting %r into sys.modules as %r." % (module.__name__, name))
    sys.modules[name] = module