- """Handle input for active users."""
-
- # get the next waiting line of input
- input_data = user.input_queue.pop(0)
-
- # split out the command (first word) and parameters (everything else)
- if input_data.find(" ") > 0:
- command_name, parameters = input_data.split(" ", 1)
- else:
- command_name = input_data
- parameters = ""
-
- # lowercase the command
- command_name = command_name.lower()
-
- # the command matches a command word for which we have data
- if command_name in universe.categories["command"]:
- command = universe.categories["command"][command_name]
- else: command = None
-
- # if it's allowed, do it
- if user.can_run(command): exec(command.get("action"))
-
- # otherwise, give an error
- elif command_name: command_error(user, input_data)
-
-def command_halt(user, parameters):
- """Halt the world."""
-
- # see if there's a message or use a generic one
- if parameters: message = "Halting: " + parameters
- else: message = "User " + user.account.get("name") + " halted the world."
-
- # let everyone know
- broadcast(message)
- log(message)
-
- # set a flag to terminate the world
- universe.terminate_world = True
-
-def command_reload(user):
- """Reload all code modules, configs and data."""
-
- # let the user know and log
- user.send("Reloading all code modules, configs and data.")
- log("User " + user.account.get("name") + " reloaded the world.")
-
- # set a flag to reload
- universe.reload_modules = True
-
-def command_help(user, parameters):
- """List available commands and provide help for commands."""
-
- # did the user ask for help on a specific command word?
- if parameters:
-
- # is the command word one for which we have data?
- if parameters in universe.categories["command"]:
- command = universe.categories["command"][parameters]
- else: command = None
-
- # only for allowed commands
- if user.can_run(command):
-
- # add a description if provided
- description = command.get("description")
- if not description:
- description = "(no short description provided)"
- if command.getboolean("administrative"): output = "$(red)"
- else: output = "$(grn)"
- output += parameters + "$(nrm) - " + description + "$(eol)$(eol)"
-
- # add the help text if provided
- help_text = command.get("help")
- if not help_text:
- help_text = "No help is provided for this command."
- output += help_text
-
- # no data for the requested command word
- else:
- output = "That is not an available command."
-
- # no specific command word was indicated
- else:
-
- # give a sorted list of commands with descriptions if provided
- output = "These are the commands available to you:$(eol)$(eol)"
- sorted_commands = universe.categories["command"].keys()
- sorted_commands.sort()
- for item in sorted_commands:
- command = universe.categories["command"][item]
- if user.can_run(command):
- description = command.get("description")
- if not description:
- description = "(no short description provided)"
- if command.getboolean("administrative"): output += " $(red)"
- else: output += " $(grn)"
- output += item + "$(nrm) - " + description + "$(eol)"
- output += "$(eol)Enter \"help COMMAND\" for help on a command named \"COMMAND\"."
-
- # send the accumulated output to the user
- user.send(output)
-
-def command_say(user, parameters):
- """Speak to others in the same room."""
-
- # check for replacement macros
- if replace_macros(user, parameters, True) != parameters:
- user.send("You cannot speak $_(replacement macros).")
-
- # the user entered a message
- elif parameters:
-
- # get rid of quote marks on the ends of the message and
- # capitalize the first letter
- message = parameters.strip("\"'`").capitalize()
-
- # a dictionary of punctuation:action pairs
- actions = {}
- for facet in universe.categories["internal"]["language"].facets():
- if facet.startswith("punctuation_"):
- action = facet.split("_")[1]
- for mark in universe.categories["internal"]["language"].getlist(facet):
- actions[mark] = action
-
- # match the punctuation used, if any, to an action
- default_punctuation = universe.categories["internal"]["language"].get("default_punctuation")
- action = actions[default_punctuation]
- for mark in actions.keys():
- if message.endswith(mark) and mark != default_punctuation:
- action = actions[mark]
- break
-
- # if the action is default and there is no mark, add one
- if action == actions[default_punctuation] and not message.endswith(default_punctuation):
- message += default_punctuation
-
- # capitalize a list of words within the message
- capitalize_words = universe.categories["internal"]["language"].getlist("capitalize_words")
- for word in capitalize_words:
- message = message.replace(" " + word + " ", " " + word.capitalize() + " ")
-
- # tell the room
- # TODO: we won't be using broadcast once there are actual rooms
- broadcast(user.avatar.get("name") + " " + action + "s, \"" + message + "\"")
-
- # there was no message
- else:
- user.send("What do you want to say?")
-
-def command_show(user, parameters):
- """Show program data."""
- message = ""
- if parameters.find(" ") < 1:
- if parameters == "time":
- message = universe.categories["internal"]["counters"].get("elapsed") + " increments elapsed since the world was created."
- elif parameters == "categories":
- message = "These are the element categories:$(eol)"
- categories = universe.categories.keys()
- categories.sort()
- for category in categories: message += "$(eol) $(grn)" + category + "$(nrm)"
- elif parameters == "files":
- message = "These are the current files containing the universe:$(eol)"
- filenames = universe.files.keys()
- filenames.sort()
- for filename in filenames: message += "$(eol) $(grn)" + filename + "$(nrm)"
- else: message = ""
- else:
- arguments = parameters.split()
- if arguments[0] == "category":
- if arguments[1] in universe.categories:
- message = "These are the elements in the \"" + arguments[1] + "\" category:$(eol)"
- elements = universe.categories[arguments[1]].keys()
- elements.sort()
- for element in elements:
- message += "$(eol) $(grn)" + universe.categories[arguments[1]][element].key + "$(nrm)"
- elif arguments[0] == "element":
- if arguments[1] in universe.contents:
- message = "These are the properties of the \"" + arguments[1] + "\" element:$(eol)"
- element = universe.contents[arguments[1]]
- facets = element.facets()
- facets.sort()
- for facet in facets:
- message += "$(eol) $(grn)" + facet + ": $(red)" + escape_macros(element.get(facet)) + "$(nrm)"
- if not message:
- if parameters: message = "I don't know what \"" + parameters + "\" is."
- else: message = "What do you want to show?"
- user.send(message)
-
-def command_create(user, parameters):
- """Create an element if it does not exist."""
- if not parameters: message = "You must at least specify an element to create."
- else:
- arguments = parameters.split()
- if len(arguments) == 1: arguments.append("")
- if len(arguments) == 2:
- element, filename = arguments
- if element in universe.contents: message = "The \"" + element + "\" element already exists."
- else:
- message = "You create \"" + element + "\" within the universe."
- logline = user.account.get("name") + " created an element: " + element
- if filename:
- logline += " in file " + filename
- if filename not in universe.files:
- message += " Warning: \"" + filename + "\" is not yet included in any other file and will not be read on startup unless this is remedied."
- Element(element, universe, filename)
- log(logline)
- elif len(arguments) > 2: message = "You can only specify an element and a filename."
- user.send(message)
-
-def command_destroy(user, parameters):
- """Destroy an element if it exists."""
- if not parameters: message = "You must specify an element to destroy."
- else:
- if parameters not in universe.contents: message = "The \"" + parameters + "\" element does not exist."
- else:
- universe.contents[parameters].destroy()
- message = "You destroy \"" + parameters + "\" within the universe."
- log(user.account.get("name") + " destroyed an element: " + parameters)
- user.send(message)
-
-def command_set(user, parameters):
- """Set a facet of an element."""
- if not parameters: message = "You must specify an element, a facet and a value."
- else:
- arguments = parameters.split(" ", 2)
- if len(arguments) == 1: message = "What facet of element \"" + arguments[0] + "\" would you like to set?"
- elif len(arguments) == 2: message = "What value would you like to set for the \"" + arguments[1] + "\" facet of the \"" + arguments[0] + "\" element?"
- else:
- element, facet, value = arguments
- if element not in universe.contents: message = "The \"" + element + "\" element does not exist."
- else:
- universe.contents[element].set(facet, value)
- message = "You have successfully (re)set the \"" + facet + "\" facet of element \"" + element + "\". Try \"show element " + element + "\" for verification."
- user.send(message)
-
-def command_delete(user, parameters):
- """Delete a facet from an element."""
- if not parameters: message = "You must specify an element and a facet."
- else:
- arguments = parameters.split(" ")
- if len(arguments) == 1: message = "What facet of element \"" + arguments[0] + "\" would you like to delete?"
- elif len(arguments) != 2: message = "You may only specify an element and a facet."
- else:
- element, facet = arguments
- if element not in universe.contents: message = "The \"" + element + "\" element does not exist."
- elif facet not in universe.contents[element].facets(): message = "The \"" + element + "\" element has no \"" + facet + "\" facet."
- else:
- universe.contents[element].delete(facet)
- message = "You have successfully deleted the \"" + facet + "\" facet of element \"" + element + "\". Try \"show element " + element + "\" for verification."
- user.send(message)
-
-def command_error(user, input_data):
- """Generic error for an unrecognized command word."""
-
- # 90% of the time use a generic error
- if randrange(10):
- message = "I'm not sure what \"" + input_data + "\" means..."
-
- # 10% of the time use the classic diku error
- else:
- message = "Arglebargle, glop-glyf!?!"
-
- # send the error message
- user.send(message)
+ u"""Handle input for active users."""
+
+ # get the next waiting line of input
+ input_data = user.input_queue.pop(0)
+
+ # is there input?
+ if input_data:
+
+ # split out the command and parameters
+ actor = user.avatar
+ mode = actor.get(u"mode")
+ if mode and input_data.startswith(u"!"):
+ command_name, parameters = first_word(input_data[1:])
+ elif mode == u"chat":
+ command_name = u"say"
+ parameters = input_data
+ else:
+ command_name, parameters = first_word(input_data)
+
+ # lowercase the command
+ command_name = command_name.lower()
+
+ # the command matches a command word for which we have data
+ if command_name in universe.categories[u"command"]:
+ command = universe.categories[u"command"][command_name]
+ else: command = None
+
+ # if it's allowed, do it
+ if actor.can_run(command): exec(command.get(u"action"))
+
+ # otherwise, give an error
+ elif command_name: command_error(actor, input_data)
+
+ # if no input, just idle back with a prompt
+ else: user.send(u"", just_prompt=True)
+
+def command_halt(actor, parameters):
+ u"""Halt the world."""
+ if actor.owner:
+
+ # see if there's a message or use a generic one
+ if parameters: message = u"Halting: " + parameters
+ else:
+ message = u"User " + actor.owner.account.get(
+ u"name"
+ ) + u" halted the world."
+
+ # let everyone know
+ broadcast(message, add_prompt=False)
+ log(message, 8)
+
+ # set a flag to terminate the world
+ universe.terminate_flag = True
+
+def command_reload(actor):
+ u"""Reload all code modules, configs and data."""
+ if actor.owner:
+
+ # let the user know and log
+ actor.send(u"Reloading all code modules, configs and data.")
+ log(
+ u"User " + actor.owner.account.get(u"name") + u" reloaded the world.",
+ 8
+ )
+
+ # set a flag to reload
+ universe.reload_flag = True
+
+def command_quit(actor):
+ u"""Leave the world and go back to the main menu."""
+ if actor.owner:
+ actor.owner.state = u"main_utility"
+ actor.owner.deactivate_avatar()
+
+def command_help(actor, parameters):
+ u"""List available commands and provide help for commands."""
+
+ # did the user ask for help on a specific command word?
+ if parameters and actor.owner:
+
+ # is the command word one for which we have data?
+ if parameters in universe.categories[u"command"]:
+ command = universe.categories[u"command"][parameters]
+ else: command = None
+
+ # only for allowed commands
+ if actor.can_run(command):
+
+ # add a description if provided
+ description = command.get(u"description")
+ if not description:
+ description = u"(no short description provided)"
+ if command.getboolean(u"administrative"): output = u"$(red)"
+ else: output = u"$(grn)"
+ output += parameters + u"$(nrm) - " + description + u"$(eol)$(eol)"
+
+ # add the help text if provided
+ help_text = command.get(u"help")
+ if not help_text:
+ help_text = u"No help is provided for this command."
+ output += help_text
+
+ # list related commands
+ see_also = command.getlist(u"see_also")
+ if see_also:
+ really_see_also = u""
+ for item in see_also:
+ if item in universe.categories[u"command"]:
+ command = universe.categories[u"command"][item]
+ if actor.can_run(command):
+ if really_see_also:
+ really_see_also += u", "
+ if command.getboolean(u"administrative"):
+ really_see_also += u"$(red)"
+ else:
+ really_see_also += u"$(grn)"
+ really_see_also += item + u"$(nrm)"
+ if really_see_also:
+ output += u"$(eol)$(eol)See also: " + really_see_also
+
+ # no data for the requested command word
+ else:
+ output = u"That is not an available command."
+
+ # no specific command word was indicated
+ else:
+
+ # give a sorted list of commands with descriptions if provided
+ output = u"These are the commands available to you:$(eol)$(eol)"
+ sorted_commands = universe.categories[u"command"].keys()
+ sorted_commands.sort()
+ for item in sorted_commands:
+ command = universe.categories[u"command"][item]
+ if actor.can_run(command):
+ description = command.get(u"description")
+ if not description:
+ description = u"(no short description provided)"
+ if command.getboolean(u"administrative"): output += u" $(red)"
+ else: output += u" $(grn)"
+ output += item + u"$(nrm) - " + description + u"$(eol)"
+ output += u"$(eol)Enter \"help COMMAND\" for help on a command " \
+ + u"named \"COMMAND\"."
+
+ # send the accumulated output to the user
+ actor.send(output)
+
+def command_move(actor, parameters):
+ u"""Move the avatar in a given direction."""
+ if parameters in universe.contents[actor.get(u"location")].portals():
+ actor.move_direction(parameters)
+ else: actor.send(u"You cannot go that way.")
+
+def command_look(actor, parameters):
+ u"""Look around."""
+ if parameters: actor.send(u"You can't look at or in anything yet.")
+ else: actor.look_at(actor.get(u"location"))
+
+def command_say(actor, parameters):
+ u"""Speak to others in the same room."""
+ import unicodedata
+
+ # check for replacement macros
+ if replace_macros(actor.owner, parameters, True) != parameters:
+ actor.send(u"You cannot speak $_(replacement macros).")
+
+ # the user entered a message
+ elif parameters:
+
+ # get rid of quote marks on the ends of the message
+ message = parameters.strip(u"\"'`")
+
+ # match the punctuation used, if any, to an action
+ actions = universe.categories[u"internal"][u"language"].getdict(
+ u"actions"
+ )
+ default_punctuation = universe.categories[u"internal"][u"language"].get(
+ u"default_punctuation"
+ )
+ action = u""
+ for mark in actions.keys():
+ if message.endswith(mark):
+ action = actions[mark]
+ break
+
+ # add punctuation if needed
+ if not action:
+ action = actions[default_punctuation]
+ if message and not unicodedata.category(message[-1]) == u"Po":
+ message += default_punctuation
+
+ # decapitalize the first letter to improve matching
+ message = message[0].lower() + message[1:]
+
+ # iterate over all words in message, replacing typos
+ typos = universe.categories[u"internal"][u"language"].getdict(u"typos")
+ words = message.split()
+ for index in range(len(words)):
+ word = words[index]
+ while unicodedata.category(word[0]) == u"Po":
+ word = word[1:]
+ while unicodedata.category(word[-1]) == u"Po":
+ word = word[:-1]
+ if word in typos.keys():
+ words[index] = words[index].replace(word, typos[word])
+ message = u" ".join(words)
+
+ # capitalize the first letter
+ message = message[0].upper() + message[1:]
+
+ # tell the room
+ actor.echo_to_location(
+ actor.get(u"name") + u" " + action + u"s, \"" + message + u"\""
+ )
+ actor.send(u"You " + action + u", \"" + message + u"\"")
+
+ # there was no message
+ else:
+ actor.send(u"What do you want to say?")
+
+def command_chat(actor):
+ u"""Toggle chat mode."""
+ mode = actor.get(u"mode")
+ if not mode:
+ actor.set(u"mode", u"chat")
+ actor.send(u"Entering chat mode (use $(grn)!chat$(nrm) to exit).")
+ elif mode == u"chat":
+ actor.remove_facet(u"mode")
+ actor.send(u"Exiting chat mode.")
+ else: actor.send(u"Sorry, but you're already busy with something else!")
+
+def command_show(actor, parameters):
+ u"""Show program data."""
+ import re
+ message = u""
+ arguments = parameters.split()
+ if not parameters: message = u"What do you want to show?"
+ elif arguments[0] == u"time":
+ message = universe.categories[u"internal"][u"counters"].get(
+ u"elapsed"
+ ) + u" increments elapsed since the world was created."
+ elif arguments[0] == u"categories":
+ message = u"These are the element categories:$(eol)"
+ categories = universe.categories.keys()
+ categories.sort()
+ for category in categories:
+ message += u"$(eol) $(grn)" + category + u"$(nrm)"
+ elif arguments[0] == u"files":
+ message = u"These are the current files containing the universe:$(eol)"
+ filenames = universe.files.keys()
+ filenames.sort()
+ for filename in filenames:
+ if universe.files[filename].is_writeable(): status = u"rw"
+ else: status = u"ro"
+ message += u"$(eol) $(red)(" + status + u") $(grn)" + filename \
+ + u"$(nrm)"
+ elif arguments[0] == u"category":
+ if len(arguments) != 2: message = u"You must specify one category."
+ elif arguments[1] in universe.categories:
+ message = u"These are the elements in the \"" + arguments[1] \
+ + u"\" category:$(eol)"
+ elements = [
+ (
+ universe.categories[arguments[1]][x].key
+ ) for x in universe.categories[arguments[1]].keys()
+ ]
+ elements.sort()
+ for element in elements:
+ message += u"$(eol) $(grn)" + element + u"$(nrm)"
+ else: message = u"Category \"" + arguments[1] + u"\" does not exist."
+ elif arguments[0] == u"file":
+ if len(arguments) != 2: message = u"You must specify one file."
+ elif arguments[1] in universe.files:
+ message = u"These are the elements in the \"" + arguments[1] \
+ + u"\" file:$(eol)"
+ elements = universe.files[arguments[1]].data.sections()
+ elements.sort()
+ for element in elements:
+ message += u"$(eol) $(grn)" + element + u"$(nrm)"
+ else: message = u"Category \"" + arguments[1] + u"\" does not exist."
+ elif arguments[0] == u"element":
+ if len(arguments) != 2: message = u"You must specify one element."
+ elif arguments[1] in universe.contents:
+ element = universe.contents[arguments[1]]
+ message = u"These are the properties of the \"" + arguments[1] \
+ + u"\" element (in \"" + element.origin.filename + u"\"):$(eol)"
+ facets = element.facets()
+ facets.sort()
+ for facet in facets:
+ message += u"$(eol) $(grn)" + facet + u": $(red)" \
+ + escape_macros(element.get(facet)) + u"$(nrm)"
+ else: message = u"Element \"" + arguments[1] + u"\" does not exist."
+ elif arguments[0] == u"result":
+ if len(arguments) < 2: message = u"You need to specify an expression."
+ else:
+ try:
+ message = repr(eval(u" ".join(arguments[1:])))
+ except:
+ message = u"Your expression raised an exception!"
+ elif arguments[0] == u"log":
+ if len(arguments) == 4:
+ if re.match(u"^\d+$", arguments[3]) and int(arguments[3]) >= 0:
+ stop = int(arguments[3])
+ else: stop = -1
+ else: stop = 0
+ if len(arguments) >= 3:
+ if re.match(u"^\d+$", arguments[2]) and int(arguments[2]) > 0:
+ start = int(arguments[2])
+ else: start = -1
+ else: start = 10
+ if len(arguments) >= 2:
+ if re.match(u"^\d+$", arguments[1]) and 0 <= int(arguments[1]) <= 9:
+ level = int(arguments[1])
+ else: level = -1
+ elif 0 <= actor.owner.account.getint(u"loglevel") <= 9:
+ level = actor.owner.account.getint(u"loglevel")
+ else: level = 1
+ if level > -1 and start > -1 and stop > -1:
+ message = get_loglines(level, start, stop)
+ else:
+ message = u"When specified, level must be 0-9 (default 1), " \
+ + u"start and stop must be >=1 (default 10 and 1)."
+ else: message = u"I don't know what \"" + parameters + u"\" is."
+ actor.send(message)
+
+def command_create(actor, parameters):
+ u"""Create an element if it does not exist."""
+ if not parameters:
+ message = u"You must at least specify an element to create."
+ elif not actor.owner: message = u""
+ else:
+ arguments = parameters.split()
+ if len(arguments) == 1: arguments.append(u"")
+ if len(arguments) == 2:
+ element, filename = arguments
+ if element in universe.contents:
+ message = u"The \"" + element + u"\" element already exists."
+ else:
+ message = u"You create \"" + element + u"\" within the universe."
+ logline = actor.owner.account.get(
+ u"name"
+ ) + u" created an element: " + element
+ if filename:
+ logline += u" in file " + filename
+ if filename not in universe.files:
+ message += u" Warning: \"" + filename \
+ + u"\" is not yet included in any other file and will " \
+ + u"not be read on startup unless this is remedied."
+ Element(element, universe, filename)
+ log(logline, 6)
+ elif len(arguments) > 2:
+ message = u"You can only specify an element and a filename."
+ actor.send(message)
+
+def command_destroy(actor, parameters):
+ u"""Destroy an element if it exists."""
+ if actor.owner:
+ if not parameters: message = u"You must specify an element to destroy."
+ else:
+ if parameters not in universe.contents:
+ message = u"The \"" + parameters + u"\" element does not exist."
+ else:
+ universe.contents[parameters].destroy()
+ message = u"You destroy \"" + parameters \
+ + u"\" within the universe."
+ log(
+ actor.owner.account.get(
+ u"name"
+ ) + u" destroyed an element: " + parameters,
+ 6
+ )
+ actor.send(message)
+
+def command_set(actor, parameters):
+ u"""Set a facet of an element."""
+ if not parameters:
+ message = u"You must specify an element, a facet and a value."
+ else:
+ arguments = parameters.split(u" ", 2)
+ if len(arguments) == 1:
+ message = u"What facet of element \"" + arguments[0] \
+ + u"\" would you like to set?"
+ elif len(arguments) == 2:
+ message = u"What value would you like to set for the \"" \
+ + arguments[1] + u"\" facet of the \"" + arguments[0] \
+ + u"\" element?"
+ else:
+ element, facet, value = arguments
+ if element not in universe.contents:
+ message = u"The \"" + element + u"\" element does not exist."
+ else:
+ universe.contents[element].set(facet, value)
+ message = u"You have successfully (re)set the \"" + facet \
+ + u"\" facet of element \"" + element \
+ + u"\". Try \"show element " + element + u"\" for verification."
+ actor.send(message)
+
+def command_delete(actor, parameters):
+ u"""Delete a facet from an element."""
+ if not parameters: message = u"You must specify an element and a facet."
+ else:
+ arguments = parameters.split(u" ")
+ if len(arguments) == 1:
+ message = u"What facet of element \"" + arguments[0] \
+ + u"\" would you like to delete?"
+ elif len(arguments) != 2:
+ message = u"You may only specify an element and a facet."
+ else:
+ element, facet = arguments
+ if element not in universe.contents:
+ message = u"The \"" + element + u"\" element does not exist."
+ elif facet not in universe.contents[element].facets():
+ message = u"The \"" + element + u"\" element has no \"" + facet \
+ + u"\" facet."
+ else:
+ universe.contents[element].remove_facet(facet)
+ message = u"You have successfully deleted the \"" + facet \
+ + u"\" facet of element \"" + element \
+ + u"\". Try \"show element " + element + u"\" for verification."
+ actor.send(message)
+
+def command_error(actor, input_data):
+ u"""Generic error for an unrecognized command word."""
+ import random
+
+ # 90% of the time use a generic error
+ if random.randrange(10):
+ message = u"I'm not sure what \"" + input_data + u"\" means..."
+
+ # 10% of the time use the classic diku error
+ else:
+ message = u"Arglebargle, glop-glyf!?!"
+
+ # send the error message
+ actor.send(message)
+
+def daemonize():
+ u"""Fork and disassociate from everything."""
+ import codecs, os, sys
+ if universe.contents[u"internal:process"].getboolean(u"daemon"):
+ log(u"Disassociating from the controlling terminal.")
+ if os.fork(): os._exit(0)
+ os.setsid()
+ if os.fork(): os._exit(0)
+ os.chdir(u"/")
+ os.umask(0)
+ for stdpipe in range(3): os.close(stdpipe)
+ sys.stdin = codecs.open(u"/dev/null", u"r", u"utf-8")
+ sys.__stdin__ = codecs.open(u"/dev/null", u"r", u"utf-8")
+ sys.stdout = codecs.open(u"/dev/null", u"w", u"utf-8")
+ sys.stderr = codecs.open(u"/dev/null", u"w", u"utf-8")
+ sys.__stdout__ = codecs.open(u"/dev/null", u"w", u"utf-8")
+ sys.__stderr__ = codecs.open(u"/dev/null", u"w", u"utf-8")
+
+def create_pidfile(universe):
+ u"""Write a file containing the current process ID."""
+ import codecs, os, os.path
+ pid = unicode(os.getpid())
+ log(u"Process ID: " + pid)
+ file_name = universe.contents[u"internal:process"].get(u"pidfile")
+ if file_name:
+ if not os.path.isabs(file_name):
+ file_name = os.path.join(universe.startdir, file_name)
+ file_descriptor = codecs.open(file_name, u"w", u"utf-8")
+ file_descriptor.write(pid + u"\n")
+ file_descriptor.flush()
+ file_descriptor.close()
+
+def remove_pidfile(universe):
+ u"""Remove the file containing the current process ID."""
+ import os, os.path
+ file_name = universe.contents[u"internal:process"].get(u"pidfile")
+ if file_name:
+ if not os.path.isabs(file_name):
+ file_name = os.path.join(universe.startdir, file_name)
+ if os.access(file_name, os.W_OK): os.remove(file_name)
+
+def excepthook(excepttype, value, tracebackdata):
+ u"""Handle uncaught exceptions."""
+ import traceback
+
+ # assemble the list of errors into a single string
+ message = u"".join(
+ traceback.format_exception(excepttype, value, tracebackdata)
+ )
+
+ # try to log it, if possible
+ try: log(message, 9)
+ except: pass
+
+ # try to write it to stderr, if possible
+ try: sys.stderr.write(message)
+ except: pass
+
+def sighook(what, where):
+ u"""Handle external signals."""
+ import signal
+
+ # a generic message
+ message = u"Caught signal: "
+
+ # for a hangup signal
+ if what == signal.SIGHUP:
+ message += u"hangup (reloading)"
+ universe.reload_flag = True
+
+ # for a terminate signal
+ elif what == signal.SIGTERM:
+ message += u"terminate (halting)"
+ universe.terminate_flag = True
+
+ # catchall for unexpected signals
+ else: message += unicode(what) + u" (unhandled)"
+
+ # log what happened
+ log(message, 8)
+
+# redefine sys.excepthook with ours
+import sys
+sys.excepthook = excepthook
+
+# assign the sgnal handlers
+import signal
+signal.signal(signal.SIGHUP, sighook)
+signal.signal(signal.SIGTERM, sighook)