OBJECT
  /secure/master

LAST UPDATE
  Mateese, 27-Apr-1994, 04:00 MEST

SYNOPSIS
  #include "/secure/config.h"

  MASTER->...

DESCRIPTION
  The master is the gateway between the gamedriver and the mudlib to
  perform actions with mudlib specific effects.
  Since it is the first loaded object, it has also to implement the
  basic security functions, which are then used throughout the mudlib.
  Same applies for the functions dealing with pathnames.

  Implementation Note:
    The security functions are implemented using a twodimensional
    matrix mapping (perm_matrix[perm1][perm2]), holding for each
    ...ID combination a comparison flag: 1: perm1 > perm2,
    0: perm1 = perm2, -1: perm1 < perm2, and -2: the two perms are not
    directly comparable.
    In the latter case, further investigation might be necessary.
    Two arrays (wlist and dlist) hold the permission IDs allowed for
    wizards resp. domain matters.

  Functions of common interest:

    nomask static void init_matrices ()
      Sets up the security variables perm_matrix, wlist and dlist.

    nomask void create()
      Checks if the object is the "/secure/master", and calls
      init_matrices(). If the check fails, the object is destructed.

    string * _normalize (string path, string user)
      Normalize a given filename.
        path: The filename to normalize.
        user: The name to use with relative filenames (may be 0).
              It may be an ID-permission, which is then filtered out.
      Result:
        The normalized filename, split up by it's '/'.
      Besides the elimination of embedded '..' the function expands
      following constructs:
        /...        is treated normally.
        ~<name>/... is replaced by /w/<name>/...
        ~/...       is replaced by /w/<user/... if <user> is defined
        +<name>/... is replaced by /d/<name>/...
        ...         is replaced by <TP.CurrentDir>/... if TP is <user>
                                by <file_name(PREV)::DirPart>/... else.

    string _stime (void|int date)
      Convert the given or current time into a string.
        date : The numeric time as returned by time() to convert.
               Default is time().
      Result:
        The time as a string in a more european manner:
        Example: 'Mon 15-Jun-1992 20:00:00'

    string dump_current (void|int full, void|object ob, void|string txt)
      Dump the current call state into one string.
        full : If 0, just the previous object is dumped, else all
               previous objects.
        ob   : An optional object to go first, may be 0.
        txt  : The string to prefix <ob>.
      Result:
        A printable string of the current call state.
        All dumped entries (except for ob) are indented by 3 spaces.
      If this function is called by the master itself, that call is not
      dumped.
      It is used for logs when detecting security violations.


FUNCTION REFERENCE

    nomask static void init_matrices ()
      Initializes the security mappings and arrays.

    nomask void create()
      Initializes the master object.

    string * _normalize (string path, string user)
      Normalize a given filename.

    string _stime (void|int date)
      Convert the given or current time into a string.

    string dump_current (void|int full, void|object ob, void|string txt)
      Dump the current call state into one string.


  Initialisation

    void reset ()
      Perform reset handling: trigger a garbage_collection().

    void inaugurate_master (int arg)
      Perform mudlib specific setup of the master.

    void flag (string arg)
      Evaluate an argument given as option '-f' to the driver.

    string *define_include_dirs ()
      Define where the include files are searched.

    static string * _file_array (string file)
      Auxiliary function to epilog()

    string *epilog (int eflag)
      Perform final actions before opening the game to players.

    void preload (string file)
      Preload a given object.

    void external_master_reload ()

    void reactivate_destructed_master (int removed)
      Reactivate a formerly destructed master.

    string get_simul_efun ()
      Load the simul_efun object and return its path.


  Handling of player connections

    object connect ()
      Handle the request for a new connection.

    void remove_player (object player)
      Remove a player object from the game.

    void disconnect (object obj)
      Handle the loss of an IP connection.


  Runtime Support

    object compile_object (string filename)
      Compile an virtual object.

    string get_wiz_name (mixed file)
      Return the author of a file.

    string object_name (object obj)
      Return a printable name for an object.

    void destruct_environment (object obj)
      Remove an object from its environment which is destructed.

    void move_or_destruct (object what, object to)
      Rescue an object from an destructed environment.

    mixed prepare_destruct (object obj)
      Prepare the destruction of the given object.

    void quota_demon (void)
      Handle quotas in times of memory shortage.

    void receive_imp (string host, string msg)
      Handle a received IMP message.

    void slow_shut_down (int minutes)
      Schedule a shutdown for the near future.

    void notify_shutdown (void)
      Notify the master about an immediate shutdown.


  Security and Permissions

    string _domain_prot (string prot)
      Return the name of the domain if the given protection concerns
      domain matters.

    string _get_perm (object obj, string domain)
      Get the permission of an object.

    static string *_get_prot_normal (string *path)
      Get the protections for a file.

    string *_get_prot (string file, mixed user)
      Get the protections for a file.

    int _compare_perms (string perm1, string perm2)
      Compare two permissions/protections.

    string _effective_perm (void|string domain, void|mixed skip)
      Evaluate the current effective permission.

    int privilege_violation (string op, mixed who, mixed arg, mixed arg2)
      Validate the execution of a privileged operation.

    int query_allow_shadow (object victim)
      Validate a shadowing.

    int prevent_shadow(object shadower)
      Deny shadowing of the master.

    int query_player_level (string what)
      Check if the player is of high enough level for several things.

    int valid_exec (string name)
      Validate the rebinding of an IP connection by usage of efun exec().

    int valid_query_snoop (object obj)
      Validate if the snoopers of an object may be revealed by usage
      of the efun query_snoop().

    int valid_snoop (object snoopee, object snooper)
      Validate the start/stop of a snoop.


  Userids and depending Security

    string creator_file (mixed obj)
      Return the basic uid for an object.

    string get_root_uid ()
      Return the string to be used as root-uid.

    string get_bb_uid()
      Return the string to be used as backbone-uid.

    int valid_seteuid (object obj, string neweuid)
      Validate the change of an objects euid by efun seteuid().

    string valid_read (string path, string euid, string fun
                      , object caller)
      Validate a reading file operation.

    string valid_write (string path, string euid, string fun
                       , object caller)
      Validate a writing file operation.


  Error Handling

    string *error_logfile (mixed file)
      Return one or more approbiate username(s) for an error logfile.

    void dangling_lfun_closure ()
      Handle a dangling lfun-closure.

    void log_error (string file, string err)
      Announce a compile-time error.

    void runtime_error (string err, string prg, string curobj, int line)
      Announce a runtime error.

    mixed heart_beat_error (object culprit, string err
                           , string prg, string curobj, int line)
      Announce an error in the heart_beat() function.


  ed() Support

    string make_path_absolute (string str)
      Absolutize a relative filename given to the editor.

    int save_ed_setup (object who, int code)
      Save individual settings of ed for a wizard.

    int retrieve_ed_setup (object who)
      Retrieve individual settings of ed for a wizard.

    string get_ed_buffer_save_file_name (string file)
      Return a filename for the ed buffer to be save into.


 parse_command() Support

   string *parse_command_id_list ()
     Return generic singular ids.

   string *parse_command_plural_id_list ()
     Return generic plural ids.

   string *parse_command_adjectiv_id_list ()
     Return generic adjective ids.

   string *parse_command_prepos_list ()
     Return common prepositions.

   string parse_command_all_word()
     Return the one(!) 'all' word.


DESCRIPTION -- Initialisation

    These functions are called after (re)loading the master to establish
    the most basic operation parameters.

    The initialisation of LPMud on startup follows this path:
      - The gamedriver evaluates the commandline options and initializes
        itself.
      - The master is loaded, and thus it's create() (!compat only) and
        its reset() is called.
      - get_root_uid() is called. If the result is valid, it becomes the
        masters uid and euid.
      - get_bb_uid() is called.
      - inaugurate_master() is called.
      - flag() is called for each given '-f' commandline option.
      - get_simul_efun() is called.
      - define_include_dirs() is called.
      - Preloading is done:
          compat : The filenames of the objects are read from INIT_FILE
                   and the objects are loaded. Then epilog() is called.
          !compat: epilog() is called. If it returns an array of strings,
                   it is considered holding the filenames of the objects
                   to preload. They are then given one at a time as
                   argument to preload() which does the actual
                   preloading.
      - The gamedriver sets up the IP communication and enters the
        backend loop.

    If the master is reloaded during the game, this actions are taken:
      - The master is loaded, and thus it's create() (!compat only) and
        its reset() is called.
      - Any auto-include string is cleared.
      - get_root_uid() is called. If the result is valid, it becomes the
        masters uid and euid.
      - inaugurate_master() is called.

    If the master was destructed, but couldn't be reloaded, the old
    master object could be reactivated. In that case:
      - reactivate_destructed_master() is called.
      - inaugurate_master() is called.

    The functions in detail:

    void reset ()
      After a protocol write, a garbage collection is triggered.

    void inaugurate_master (int arg)
      Perform setup of the master.
        arg: 0 if the mud just started.
             1 if the master is a reactivated destructed one, which lost
                  all variables.
             2 if the master is reactivated destructed one.
             3 if the master was just reloaded.
      This function is called whenever the master becomes fully
      operational after (re)loading. This doesn't imply that the game is
      up and running.
      In case 0, the time() is stored in "/log/adm/reboot_time" for uptime
      computations.
      In cases 1 and 2, the security matrices are re-initialized.
      In all cases. the auto_include string is setup, and the master
      gets the ROOTID.

    void flag (string arg)
      Evaluate an argument given as option '-f' to the driver.
        arg: The argument string from the option text '-f<arg>'.
             If several '-f' options are given, this function
             will be called sequentially with all given arguments.
      This function is called only when the game is started.
      Currently these commands are implemented:
      '-fcall <ob> <fun> <arg>'
        call function <fun> in object <ob> with argument <arg>.
      '-fcall <ob> <fun>'
        call function <fun> in object <ob>.
      '-fshutdown'
        shutdown the game immediately.

    string *define_include_dirs ()
      Define where the include files are searched.
      Result:
        An array of string patterns giving the absolut paths where to
        search an include file. The patterns have to have a %s at the
        place where the name given in the include statement has to be
        inserted.
      The current setting searches in the directories /sys/ and
      /rsc/sys/,

    static string * _file_array (string file)
      Read a file as array.
        file: the name of the file to read.
      Result:
        The files contents, exploded by '\n'. If the file is empty or
        unreadable, ({}) is returned.
      This is an auxiliary function to epilog.

    string *epilog (int eflag)
      Perform final actions before opening the game to players.
        eflag: This is the number of '-e' options given to the parser.
               If non-zero, the function immediately returns with 0.
      Result:
        An array of strings, which designate the objects to be
        preloaded with preload().
        Any other result is interpreted as 'no object to preload'.
        The resulting strings will be passed one at the time as
        arguments to preload().
      The games start will be logged in /log/adm/game.
      If <eflag> is zero, the files "preload_files" from the directories
      /adm, /rsc and /d will be read, splitted into their lines, and
      the combined result will be returned as files to preload.

    void preload (string file)
      Preload a given object.
        file: The filename of the object to preload, as returned by
              epilog().
      If <file> is a valid name, the object is loaded, and the load
      time is written out.
      Empty <file>, or such starting with ';' or '#' are ignored.

    void external_master_reload)=
      Called if the master was reloaded externally.
      If the gamedriver destruct and reloads the master on external
      request via SIGUSR1, it does this by a call to this function.
      However, it will be called after inaugurate_master() of course.
      Currently, this function is unused.

    void reactivate_destructed_master (int removed)
      Reactivate a formerly destructed master.
        removed: True if the master was already on the list of
                 destructed objects.
      This function is called in an formerly destructed master since
      a new master couldn't be loaded.
      The function reinitializes all variables (read: the security
      matrices).

    string get_simul_efun ()
      Load the simul_efun object and return its path.
      Result:
        Either a single string with the file_name() of the
        simul_efun object, or an array of strings which has to start
        with that file_name().
        Return 0 if this feature isn't wanted.
      The function tries in sequence to load and return SIMUL_EFUN or
      SPARE_SIMUL_EFUN. If none of both can be loaded. the game is
      shut down.


DESCRIPTION -- Handling of player connections

    object connect ()
      Handle the request for a new connection.
      Result:
        The secure/login object the requested connection should be
        bound to.

    void remove_player (object player)
      Remove a player object from the game.
        player: The player object to be removed.
      The function tries to ->quit() the player, and if this fails,
      destructs it.
      This function is called by the gamedriver to expell remaining
      players from the game on shutdown in a polite way.
      If this functions fails to quit/destruct the player, it will be
      destructed the hard way by the gamedriver.
      Note: This function must not generate runtime errors.

    void disconnect (object obj)
      Handle the loss of an IP connection.
        obj: The formerly interactive object (player).
      If the layer is a guest ("GuestNo" != 0), it is removed using
      remove_player(), else ->Netdead(0) is called to inform the
      player about its state.
      This called by the gamedriver to handle the removal of an IP
      connection, either because the connection is already lost
      ('Netdeath') or due to calls to exec() or remove_interactive().
      The connection will be unbound upon return from this call.


DESCRIPTION -- Runtime Support

    object compile_object (string filename)
      Compile an virtual object.
        previous_object(): The object requesting the virtual object.
        filename         : The requested filename for the virtual object.
      Result:
        The object to serve as the requested virtual object, or 0.
      This function is called if the compiler can't find the filename
      for an object to compile. The master has now the opportunity to
      return an other which will then serve as if it was compiled from
      <filename>. For this it calls ->compile_object(<filename>)
      in the previous_object(), unless it has ROOTID, and returns
      the result from that call.
      If the master returns 0, the usual 'Could not load'-error will
      occur.

    string get_wiz_name (mixed file)
      Return the author of a file.
        file: The name of the file in question.
      Result:
        The name of the file's author (or 0 if there is none).
      This function is called for maintenance of the wiz-list, to assign
      scores to the right wizard.
      Micro does it this way:
       - Files in /w/<wizname>/*        return <wizname>
       - Files in /d/<domain>/<wizname> return <wizname>.
       - Other files in /d/<domain>/*   return <domain>.
       - All other files                return 0.

    string object_name (object obj)
      Return a printable name for an object.
        obj: The object which name is of interest.
      Result:
        A string with the object name, or 0.
      This function is called by sprintf() to print a meaningful name
      in addition to the normal file_name().
      Currently it is not implemented.

    void destruct_environment (object obj)
      Remove an object from its environment which is destructed.
        obj: The object whose enviroment is under destruction.
      During the destruction of an object is destructed, this function
      is called with every item in that object.
      Interactive objects are notified, and (TODO) might be moved
      at some save place.

    void move_or_destruct (object what, object to)
      Rescue an object from an destructed environment.
        what: The object to be rescued.
        to  : The destination of the object to be rescued.
      The <what> object is attempted to be moved into <to>.
      If that fails, <what> is destructed.
      An error in this function can be very nasty. Note that
      unlimited recursion is likely to cause errors when
      environments are deeply nested

    mixed prepare_destruct (object obj)
      Prepare the destruction of the given object.
        obj : The object to destruct.
      Result:
        Return 0 if the object is ready for destruction, any other
        value will abort the attempt.
        If a string is returned, an error with the string as
        message will be issued.
      The gamedriver calls this function whenever an object shall be
      destructed. It expects, that this function cleans the inventory
      of the object, or the destruct will fail.
      If <obj> has no environment, destruct_environment() is called
      for all contained objects, and if this doesn't move them away,
      they are destructed as well.
      If <obj> has an environment, all contained are moved into it
      using move_or_destruct().

    void quota_demon (void)
      Handle quotas in times of memory shortage.
      This function is called during the final phase of a garbage
      collection if the reserved user area couldn't be reallocated.
      This function (or a called demon) has now the opportunity to
      remove some (still active) objects from the game. If this does
      not free enough memory to reallocate the user reserve,
      slow_shut_down() will be called to start Armageddon.
      Note: Up to now, the wizlist lacks various informations needed
            to detect the memory-hungriest wizards.
      This function is not implemented.

    void receive_imp (string host, string msg)
      Handle a received IMP message.
        host: Name of the host the message comes from.
        msg : The received message.
      This function is called for every message received on the
      IMP port. It logs the message in /log/adm/impmsgs.

    void slow_shut_down (int minutes)
      Schedule a shutdown for the near future.
        minutes: The desired time in minutes till the shutdown:
                  six, if just the user reserve has been put intp use;
                  one, if the (smaller) master reserve has been put
                       into use as well.
      The gamedriver calls this function when it runs low on memory.
      At this time, it has freed its reserve, but since it won't last
      long, the games needs to be shut down.
      For this, the ARMAGEDDON object is cloned and activated with
      the number of <minutes> left.
      The delay is to give the players the opportunity to finish
      quests, sell their stuff, etc.

  Technical:
    The memory handling of the gamedriver includes three reserved
    areas: user, system and master. All three are there to insure
    that the game shuts down gracefully when the memory runs out:
    the user area to give the players time to quit normally, the
    others to enable emergency-logouts when the user reserve is
    used up as well. The areas are allocated at start of the
    gamedriver, and released when no more memory could be
    obtained from the host. In such a case, one of the remaining
    areas is freed (so the game can continue a short while) and
    a garbagecollection is initiated.
    If the garbagecollection recycles enough memory (either true
    garbage or by the aid of the quota_demon) to reallocate the
    areas, all is fine, else the game is shut down by a call to
    this function.

    void notify_shutdown (void)
      Notify the master about an immediate shutdown.
      If the gamedriver shuts down, this is the last function called
      prior to severage of all Internet connections.
      The funciton has the opportunity to perform any cleanup
      operation, like informing the mudwho server that the mud is down.
      This function is not implemented.


DESCRIPTION -- Security and Permissions

   string _domain_prot (string prot)
     Return the name of the domain if the given protection concerns
     domain matters.
       prot: the protection to analyze
     Result:
       The name of the concerned domain, or 0.

   string _get_perm (object obj, string domain)
     Get the permission of an object.
       obj   : the object
       domain: the domain name if the permission concerns domain topics.
     Result:
       The permission of the object.
       Normally this is the euid of the object (BOTTOMID if obj is 0).
       However, if the object is 'unguarded' = the euid starts with '+',
       the object's uid prepended with a '+' is used as permission.
       Alternatively, if the object is or was interactive, the permission
       as returned by SECUREINFO->Permission() is returned.

   static string *_get_prot_normal (string *path)
     Get the protections for a normalized file.
       path : the normalized exploded filename to analyze.
     Result:
       An array with the protections of the file:
         [0]: the read protection
         [1]: the write protection
         [2]: the basic object permissions

   string *_get_prot (string file, mixed user)
     Get the protections for a file.
       file: the filename to analyze
       user: The name to use with relative filenames (may be 0).
             It may be an ID-permission, which is then filtered out.
     Result:
       An array with the protections of the file:
         [0]: the read protection
         [1]: the write protection
         [2]: the basic object permissions

   int _compare_perms (string perm1, string perm2)
     Compare two permissions/protections.
       perm1 ,
       perm2 : the two permissions to compare.
     Result:
       = -2: the two perms are not compareable
       = -1: perm1 < perm2
       =  0: perm1 = perm2
       =  1: perm1 > perm2

   string _effective_perm (void|string domain, void|mixed skip)
     Evaluate the current effective permission.
       domain: the domain name if the permission concerns domain topics
       skip  : if integer, the 'n'th object to start the scan with
               else the object itself.
     Result:
       The evaluated permission.
     The function scans back through the call stack and evaluates the
     lowest common denomitor of all permissions.

   int privilege_violation (string op, mixed who, mixed arg, mixed arg2)
     Validate the execution of a privileged operation.
       op   : the requested operation (see below)
       who  : the object requesting the operation (filename or object)
       arg  : additional argument, depending on <op>.
       arg2 : additional argument, depending on <op>.
     Result:
         >0: The caller is allowed for this operation.
          0: The caller was probably misleaded; try to fix the error
       else: A real privilege violation; handle it as error.
     Privileged operations are:
       attach_erq_demon  : Attach the erq demon to object <arg> with flag <arg2>.
       bind_lambda       : Bind a lambda-closure to object <arg>.
       call_out_info     : Return an array with all call_out informations.
       input_to          : Object <who> issues an 'ignore-bang'-input_to() for
                           commandgiver <arg3>; the exakt flags are <arg4>.
       nomask simul_efun : Attempt to get an efun <arg> via efun:: when it
                           is shadowed by a 'nomask'-type simul_efun.
       rename_object     : Current object <who> renames object <arg>
                           to name <arg2>.
       send_udp          : Send UDP-data to host <arg>.
       set_auto_include_string : Set the string automatically included by
                           the compiler.
       get_extra_wizinfo : Get the additional wiz-list info for wizard <arg>.
       set_extra_wizinfo : Set the additional wiz-list info for wizard <arg>.
       set_extra_wizinfo_size : Set the size of the additional wizard info
                           in the wiz-list to <arg>.
       set_driver_hook   : Set hook <arg> to <arg2>.
       set_this_object   : Set this_object() to <arg>.
       shadow_add_action : Add an action to function <arg> from a shadow.
       symbol_variable   : Attempt to create symbol of a hidden variable
                           of object <arg> with with index <arg2> in the
                           objects variable table.
       wizlist_info      : Return an array with all wiz-list information.

     call_out_info can return the arguments to functions and lambda
     closures to be called by call_out(); you should consider that read
     access to closures, mappings and pointers means write access and/or
     other privileges.
     wizlist_info() will return an array which holds, among others, the
     extra wizlist field. While a toplevel array, if found, will be
     copied, this does not apply to nested arrays or to any mappings.
     You might also have some sensitive closures there.
     send_udp() should be watched as it could be abused to mess up
     the IMP.
     The xxx_extra_wizinfo operations are necessary for a proper wizlist
     and should therefore be restricted to admins.
     All other operations are potential sources for direct security
     breaches - any use of them should be scrutinized closely.

     The current implementation permits call_out_info(), wiz_list_info()
     and get_extra_wizinfo() to everyone, the others to ADMINs.
     If the permission is denied, it is logged in /log/adm/privilege

   int query_allow_shadow (object victim)
     Validate a shadowing.
       previous_object(): the wannabe shadow
       victim: the object to be shadowed.
     Result:
       Return 0 to disallow the shadowing, any other value to allow it.
       Destructing the shadow or the victim is another way of
       disallowing.
     The shadow is allowed if <victim> is less than ADMIN, and
     victim->prevent_shadew(shadower) returns zero.

   The master itself can't be shadowed:
     int prevent_shadow (object shadow)
       Result is always 1.

   int query_player_level (string what)
     Check if the player is of high enough level for several things.
       what: The 'thing' type (see below).
     Result:
       Return 0 to disallow, any other value to allow it.
     Types asked for so far are:
       "trace"         : Is the player is allowed to use tracing?
       "showsmallnewmalloced": Is the player allowed to issue this
                               special command?
     Both are permitted for at least Archwizards.
       "wizard"        : Is the player considered at least a "minimal"
                         wizard?
     This returns true if the wizard bit is set for this_player(),

   int valid_exec (string name)
     Validate the rebinding of an IP connection by usage of efun exec().
       name: The name of the _program_ attempting to rebind the
             connection. This is not the file_name() of the object, and
             has no leading slash.
     Result:
       Return 0 to disallow the action, any other value to allow it.
     This succeeds only for ROOTID objects.

   int valid_query_snoop (object obj)
     Validate if the snoopers of an object may be revealed by usage of
     the efun query_snoop().
       previous_object(): the asking object.
       obj              : the object which snoopers are to be revealed.
     Result:
       Return 0 to disallow the action, any other value to allow it.
     This succeeds only for ROOTID objects.

   int valid_snoop (object snoopee, object snooper)
     Validate the start/stop of a snoop.
       previous_object(): The asking object
       snoopee          : The victim of the snoop.
       snooper          : The wannabe snooper, or 0 when stopping a snoop.
     Result:
       Return 0 to disallow the action, any other value to allow it.
     This succeeds only for ROOTID objects.


DESCRIPTION -- Userids and depending Security

  micro abuses the userids to implement a completely different
  security system. We just have to take care that no object gets
  a '0' euid.

    string creator_file (mixed obj)
      Return the basic uid for an object.
        obj: The object, given by pointer or by file_name().
      Result:
        A string holding the uid of the creator, or 0.
      This function is called for newly created objects.
      If the function returns 0, the object can't be loaded and is
      destructed again.
      The uid returned is the basic object permission as returned
      by _get_prot(). Is this permission the BOTTOMID, 0 is
      returned in its place.
      The string returned by this function is called 'cuid'.

    string get_root_uid ()
      Return the string to be used as root-uid: ROOTID.

    string get_bb_uid()
      Return the string to be used as backbone-uid: ""

    int valid_seteuid (object obj, string neweuid)
      Validate the change of an objects euid by efun seteuid().
        obj    : The object requesting the new euid.
        neweuid: The new euid requested.
      Result:
        Return 0 to disallow the change, any other value to allow it.
      Rootobjects can do anything, other euid changes are allowed
      between BOTTOMID and uid, unless they exceed the current
      permissions.

    string valid_read (string path, string euid, string fun
                      , object caller)
      Validate a reading file operation.
        path   : The (possibly partial) filename given to the operation.
        euid   : The euid of the caller (might be 0).
        fun    : The name of the operation requested (see below).
        caller : The calling object.
      Result:
        The full pathname of the file to operate on, or 0 if the action
        is not allowed.
        Or return 1 to indicate that the path can be used unchanged.
     valid_read() is called for these operations:
       ed_start        (when reading a file).
       file_size
       get_dir
       print_file
       read_bytes
       read_file
       restore_object
       tail
     The operation is allowed if the effective permissions are higher
     than the files read protection.
     restore_object generally uses 0 as euid.
     ed_start defaults <path> to /w/<euid>/.err

   string valid_write (string path, string euid, string fun
                      , object caller)
     Validate a writing file operation.
       path   : The (possibly partial) filename given to the operation.
       euid   : The euid of the caller (might be 0).
       fun    : The name of the operation requested (see below).
       caller : The calling object.
     Result:
       The full pathname of the file to operate on, or 0 if the action
       is not allowed.
     valid_write() is called for these operations:
       cindent
       ed_start     (when writing a file)
       do_rename    (twice for each the old and new name)
       mkdir
       save_object
       remove_file
       rmdir
       write_bytes
       write_file
     The operation is allowed if the effective permissions are higher
     than the files write protection.
     save_object generally uses 0 as euid.
     ed_start defaults <path> to /w/<euid>/.err


DESCRIPTION -- Error Handling

  string *error_logfile (mixed file, void|int loaderr)
    Return one or more approbiate username(s) for an error logfile.
      file   : The name of file to contain the error.
               It may be the object itself so that its file_name()
               is used.
      loaderr: TRUE if the error is just a load error.
               Load errors are not logged for the standard objects
               as these happen too often.
    Result:
      An array of the fileusername(s) where the error should be logged.
    The resulting filename is constructed using the cuid derived from
    the given filename:
      no cuid        : Result = /log/err/generic
      cuid = <wizard>: Result = /w/<wizard>/.err
      cuid = <domain>: Result = /d/<domain>/.err
                                and /d/<domain>/<wizard>/.err
      cuid = <else>  : Result = /log/err/<else>


  void dangling_lfun_closure ()
    Handle a dangling lfun-closure.
    This is called when the gamedriver detects a closure using a
    vanished lfun.
    The function just raises an error.

  void log_error (string file, string err)
    Announce a compile-time error.
      file: The name of file containing the error (it needn't be an
            object file!).
      err : The error message.
    Whenever the LPC compiler detects an error, this function is called.
    The error is logged in the file(s) determined by
    error_logfile(<file>), and if this_player() is a wizard, written
    to him.

  void runtime_error (string err, string prg, string curobj, int line)
    Announce a runtime error.
      err    : The error message.
      prg    : The executed program.
      curobj : The object causing the error.
      line   : The line number where the error occured.
    This function has to announce a runtime error to the active player.
    Note that <prg> denotes actually execute program (which might be
    inherited) where <curobj> is just the offending object.
    The error is written to the appropriate error_logfile()s, and
    announced to this_player(): for wizards in form of a complete
    error message, players get a "Your sensitive mind..." message.

  mixed heart_beat_error (object culprit, string err
                         , string prg, string curobj, int line)
    Announce an error in the heart_beat() function.
      culprit: The object which lost the heart_beat.
      err    : The error message.
      prg    : The executed program (might be 0).
      curobj : The object causing the error (might be 0).
      line   : The line number where the error occured (might be 0).
    Result:
      Return anything != 0 to restart the heart_beat in culprit.
    At time of call, the heart_beat has been turned off.
    Note that <prg> denotes actually execute program (which might be
    inherited) where <curobj> is just the offending object.
    The error is logged in the appropriate error_logfile()s and
    announced to the culprit similar to runtime_error().
    The function additionally tries to destruct the offending object,
    to be able to restart the heartbeat.


DESCRIPTION -- ed() Support

  string make_path_absolute (string str)
    Absolutize a relative filename given to the editor.
      str : The relative filename (without leading slash).
    Result:
      The full pathname of the file to use.
      Any non-string result will act as 'bad file name'.
    The function returns <str> normalized.

  int save_ed_setup (object who, int code)
    Save individual settings of ed for a wizard.
      who : The wizard using the editor.
      code: The encoded options to be saved.
    Result:
      Return 0 on failure, any other value for success.
    This function saves the given integer into the file /w/<wizard/.edrc.

  int retrieve_ed_setup (object who)
    Retrieve individual settings of ed for a wizard.
      who : The wizard using the editor.
    Result:
      The encoded options retrieved (0 if there are none).
    This functions reads the .edrc-file written by save_ed_setup().

  string get_ed_buffer_save_file_name (string file)
    Return a filename for the ed buffer to be save into.
      this_player(): The wizard using the editor.
      file         : The name of the file currently in the buffer.
    Result:
      The name of the file to save the buffer into, or 0.
    This function is called whenever a wizard is destructed/goes
    netdeath while editing. Using this function, his editing is not
    done in vain.
    The result is constructed out of the given filename as
    '/w/<wizard>/.dead_ed/<file>'


DESCRIPTION -- parse_command() Support

  LPMud has a builtin support for parsing complex commands.
  It does this by requestion several types of ids from the objects.
  The same queried functions are also in the master to provide decent
  defaults, especially for generic ids like 'all the blue ones'.

  Each of the functions has to return an array of strings (with the
  exception of parse_command_all_word), each string being one of the
  ids for that type of id.

  The whole parsing has a preferrence for the english language, so the
  the code for parsing english constructs is given as well.

  micro implements these functions just for completeness.

    string *parse_command_id_list ()
      Return generic singular ids: "one" and "thing".

    string *parse_command_plural_id_list ()
      Return generic plural ids: "ones", "things" and "them".

    string *parse_command_adjectiv_id_list ()
      Return generic adjective ids.
      If there are none (like here), return some junk
      which is likely never typed, in this case "iffish".

    string *parse_command_prepos_list ()
      Return common prepositions:
        "in", "on", "under", "behind" and "beside".

    string parse_command_all_word()
      Return the one(!) 'all' word: "all".


CREDITS
  _normalize() was first written by Hyp@Nightfall

SEE ALSO
