Beispiel #1
0
def assume_uid(uid, gid, umask):
    """
    Assume the given UID, GID, and UMASK.
    """

    # First, make sure we have values.
    if uid is None:
        uid = nakedsun.settings.get("uid")
    try:
        uid = int(uid)
    except (TypeError, ValueError):
        pass

    if gid is None:
        gid = nakedsun.settings.get("gid")
    try:
        gid = int(gid)
    except (TypeError, ValueError):
        pass

    if umask is None:
        umask = nakedsun.settings.get("umask")
    try:
        umask = int(umask)
    except (TypeError, ValueError):
        if umask:
            log.warning("Invalid value for umask %r." % umask)
        umask = None

    # Do the UID first.
    if not uid is None:
        # Try assuming the new UID.
        try:
            # Make sure we're working with an integer.
            if isinstance(uid, basestring):
                try:
                    uid = pwd.getpwnam(uid).pw_uid
                except KeyError:
                    log.critical("No such user %r." % uid)
                    log.shutdown()
                    sys.exit(1)

            if os.getuid() != uid:
                # Now set it.
                os.setuid(uid)

                # Show a message.
                try:
                    log.info("Assuming the UID %d (%s)." % (uid,
                                                    pwd.getpwuid(uid).pw_name))
                except (KeyError, AttributeError):
                    log.info("Assuming the UID %d." % uid)
        except OSError:
            try:
                log.critical("Unable to assume the UID %d (%s)." % (uid,
                                                    pwd.getpwuid(uid).pw_name))
            except (KeyError, AttributeError):
                log.critical("Unable to assume the UID %d." % uid)
            log.shutdown()
            sys.exit(1)

    # Anti-Root Protection
    if os.getuid() == 0:
        if uid == 0:
            log.warning("The server is running as root. This is "
                        "not recommended.")
        else:
            log.critical("Please do not run the server as root.")
            log.critical("Set a UID via the --uid command-line argument, or "
                         "in the MUD configuration file. If the server must "
                         "run as root, provide a UID of 0.")
            log.shutdown()
            sys.exit(1)

    # Now do the GID.
    if not gid is None:
        # Try assuming the new GID.
        try:
            # Make sure we're working with an integer.
            if isinstance(gid, basestring):
                try:
                    gid = grp.getgrnam(gid).gr_gid
                except KeyError:
                    log.critical("No such group %r." % gid)
                    log.shutdown()
                    sys.exit(1)

            if os.getgid() != gid:
                # Now set it.
                os.setgid(gid)

                # Log a message.
                try:
                    log.info("Assuming the GID %d (%s)." % (gid,
                                                    grp.getgrgid(gid).gr_name))
                except (KeyError, AttributeError):
                    log.info("Assuming the GID %d." % gid)
        except OSError:
            try:
                log.critical("Unable to assume the GID %d (%s)." % (gid,
                                                    grp.getgrgid(gid).gr_name))
            except (KeyError, AttributeError):
                log.critical("Unable to assume the GID %d." % gid)
            log.shutdown()
            sys.exit(1)

    # Lastly, the umask.
    if not umask is None:
        old = os.umask(umask)
        log.info("Assuming the umask %04o (old was %04o)." % (umask, old))
Beispiel #2
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)