/*  MASTER_NAME      (#define in config.h, or as commandline option)
**  obj/master.c     (compat default)
**  secure/master.c  (native default)
**
** The master is the gateway between the gamedriver and the mudlib to perform
** actions with mudlib specific effects.
** Calls to the master by the gamedriver have an automatic catch() in effect.
**
** This skeleton names all functions called by the gamedriver and gives
** suggestions on how to program then (a few by code).
** Functions which are specific to compat or native mode are tagged as such:
**   '// !compat' means: only when not running in compat mode.
**   '// native'  means: only when running in native mode.
** and similar for every other combination.
**
** Note that the master is loaded first of all objects. Thus it is possible,
** you shouldn't inherit an other object (as most files expect the master
** to exist), nor is the compiler able to search include files
** (read: they must be specified with full path).
*/


// A short reference to all functions...
//---------------------------------------------------------------------------
//     Initialisation
//
// void inaugurate_master (int arg)
//   Perform mudlib specific setup of the master.
//
// string get_master_uid ()
//   Return the string to be used as uid (and -euid) of a (re)loaded master.
//
// void flag (string arg)
//   Evaluate an argument given as option '-f' to the driver.
//
// 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 ()
//   Called after a reload of the master on external request.
//
// void reactivate_destructed_master (int removed)
//   Reactivate a formerly destructed master.
//
// string|string * get_simul_efun ()
//   Load the simul_efun object(s) and return one or more paths of it.
//
//---------------------------------------------------------------------------
//     Handling of player connections
//
// object connect ()
//   Handle the request for a new connection.
//
// void disconnect (object obj)
//   Handle the loss of an IP connection.
//
// void remove_player (object player)
//   Remove a player object from the game.
//
// void stale_erq (closure callback)
//   Notify the loss of the erq demon.
//---------------------------------------------------------------------------
//     Runtime Support
//
// object compile_object (string filename)
//   Compile an virtual object.
//
// string get_wiz_name (string file)
//   Return the author of a file.
//
// string object_name (object obj)
//   Return a printable name for an object.
//
// 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, int port)
//   Handle a received IMP message.
//
// void slow_shut_down (int minutes)
//   Schedule a shutdown for the near future.
//
// void notify_shutdown ()
//   Notify the master about an immediate shutdown.
//
//---------------------------------------------------------------------------
//     Error Handling
//
// void dangling_lfun_closure ()
//   Handle a dangling lfun-closure.
//
// void log_error (string file, string err)
//   Announce a compiler-time error.
//
// mixed heart_beat_error (object culprit, string err,
//                         string prg, string curobj, int line)
//   Announce an error in the heart_beat() function.
//
// void runtime_error (string err, string prg, string curobj, int line)
//   Announce a runtime error.
//
//---------------------------------------------------------------------------
//     Security and Permissions
//
// 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 valid_trace (string what)
//   Check if the player may use tracing.
//
// int valid_exec (string name, object ob, object obfrom)
//   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 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().
//
// int|string valid_read  (string path, string euid, string fun, object caller)
// int|string valid_write (string path, string euid, string fun, object caller)
//   Validate a reading/writing file operation.
//
//---------------------------------------------------------------------------
//     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 saved into.
//
//---------------------------------------------------------------------------
//     parse_command() Support  (!compat, SUPPLY_PARSE_COMMAND defined)
//
// 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.
//
//---------------------------------------------------------------------------


//===========================================================================
//  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 schedule:
//   - The gamedriver evaluates the commandline options and initializes
//     itself.
//   - The master is loaded, but since the driverhooks are not set yet,
//     no standard initialisation lfun is called.
//   - get_master_uid() is called. If the result is valid, it becomes the
//     masters uid and euid.
//   - inaugurate_master() is called.
//   - flag() is called for each given '-f' commandline option.
//   - get_simul_efun() is called.
//   - the WIZLIST is read in.
//   - epilog() is called. If it returns an array of strings, they are given
//     one at a time as argument to preload().
//     Traditionally, these strings are the filenames of the objects to
//     preload, which preload() then does.
//   - 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 its initialisation lfun is called according
//     to the settings of the driverhooks (if set).
//   - Any auto-include string and all driverhooks are cleared.
//   - get_master_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.
//===========================================================================

//---------------------------------------------------------------------------
// Initialization of the master object.
//
// As the lfuns which are called to initialize objects after a load are
// defined through driver hooks, and these hooks are cleared prior to
// a master (re)load, the first function called is inaugurate_master().
// Anyway it's not very sensible to do anything earlier as the master is
// not recognized as such at that time, and so a number of (important) things
// would not work.
//
// Which lfun is called during runtime to reset the master is also depending
// on the driverhook settings. Arbitrary actions may be done on a reset.

//---------------------------------------------------------------------------
void inaugurate_master (int arg)

// Perform mudlib specific setup of the master.
//
// Argument:
//   arg: 0 if the mud just started.
//        1 if the master is reactivated destructed one.
//        2 if the master is a reactivated destructed one, which lost all
//             variables.
//        3 if the master was just reloaded.
//
// This function is called whenever the master becomes fully operational
// after (re)loading (it is now recognized as _the_ master).
// This doesn't imply that the game is up and running.
//
// This function has at least to set up the driverhooks to use. Also, any
// mudwho or wizlist handling has to be initialized here.
//
// Besides that, do whatever you feel you need to do,
// e.g. set_auto_include_string(), or give the master a decent euid.


//---------------------------------------------------------------------------
int|string get_master_uid ()

// Return the string to be used as uid (and -euid) of a (re)loaded master.
// Under !native, the function may also return a non-zero number.
// In that case, the uid is set to 0, as is the euid.


//---------------------------------------------------------------------------
void flag (string arg)

// Evaluate an argument given as option '-f' to the driver.
//
// Arguments:
//   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 can be used to pass the master commands via arguments to
// the driver. This is useful when building a new mudlib from scratch.
// It is called only when the game is started.
//
// The code given implements these commands:
//   '-fcall <ob> <fun> <arg>': call function <fun> in object <ob> with
//                              argument <arg>.
//   '-fshutdown': shutdown the game immediately.
// Thus, starting the game as 'parse "-fcall foo bar Yow!" -fshutdown' would
// first do foo->bar("Yow!") and then shutdown the game.

{
  string obj, fun, rest;

  if (arg == "shutdown")
  {
    shutdown();
    return;
  }
  if (sscanf(arg, "call %s %s %s", obj, fun, rest) >= 2)
  {
    write(obj+"->"+fun+"(\""+rest+"\") = ");
    write(call_other(obj, fun, rest));
    write("\n");
    return;
  }
  write("master: Unknown flag "+arg+"\n");
}


//---------------------------------------------------------------------------
string *epilog (int eflag)

// Perform final actions before opening the game to players.
//
// Arguments:
//   eflag: This is the number of '-e' options given to the parser.
//          Normally it is just 0 or 1.
//
// Result:
//   An array of strings, which traditionally 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().


//---------------------------------------------------------------------------
void preload (string file)

// Preload a given object.
//
// Arguments:
//   file: The filename of the object to preload, as returned by epilog().
//
// It is task of the epilog()/preload() pair to ensure the validity of
// the given strings (e.g. filtering out comments and blank lines).
// For preload itself a 'load_object(file)' is sufficient, but it
// should be guarded by a catch() to avoid premature blockings.
// Also it is wise to change the master's euid from master_uid to something
// less privileged for the time of the preload.
//
// You can of course do anything else with the passed strings - preloading
// is just the traditional task.


//---------------------------------------------------------------------------
void external_master_reload ()

// Master was reloaded on external request by SIGUSR1.
//
// If the gamedriver destruct and reloads the master on external request
// via SIGUSR1, it does this by a call to this function.
// It will be called after inaugurate_master() of course.
// If you plan to do additional magic here, you're welcome.


//---------------------------------------------------------------------------
void reactivate_destructed_master (int removed)

// Reactivate a formerly destructed master.
//
// Arguments:
//   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.
// This function has to reinitialize all variables at least to continue
// operation.


//---------------------------------------------------------------------------
string|string * get_simul_efun ()

// Load the simul_efun object(s) and return one or more paths of it.
//
// 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.
//
// Note that the object(s) must be loaded by this function!
//
// When you return an array of strings, the first string is taken as path
// to the simul_efun object, and all other paths are used for backup
// simul_efun objects to call simul_efuns that are not present in the
// main simul_efun object. This allows to remove simul_efuns at runtime
// without getting errors from old compiled programs that still use the
// obsolete simul_efuns. A side use of this mechanism is to provide
// a 'spare' simul_efun object in case the normal one fails to load.
//
// If the game depends on the simul_efun object, and none could be loaded,
// an immediate shutdown should occur.


//===========================================================================
//  Handling of player connections
//
// See also valid_exec().
//===========================================================================

//---------------------------------------------------------------------------
object connect ()

// Handle the request for a new connection.
//
// Result:
//   An login object the requested connection should be bound to.
//
// Note that the connection is not bound yet!
//
// The gamedriver will call the lfun 'logon()' in the login object after
// binding the connection to it. That lfun has to return !=0 to succeed.


//---------------------------------------------------------------------------
void disconnect (object obj)

// Handle the loss of an IP connection.
//
// Argument:
//   obj: The (formerly) interactive object (player).
//
// 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.


//---------------------------------------------------------------------------
void remove_player (object player)

// Remove a player object from the game.
//
// Argument:
//   player: The player object to be removed.
//
// 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 cause runtime errors.


//---------------------------------------------------------------------------
void stale_erq (closure callback)

// Notify the loss of the erq demon.
//
// Argument:
//   callback: the callback closure set for an erq request.
//
// If the erq connection dies prematurely, the driver will call this lfun for
// every pending request with set callback. This function should notify the
// originating object that the answer will never arrive.


//===========================================================================
//  Runtime Support
//
// Various functions used to implement advanced runtime features.
//===========================================================================

//---------------------------------------------------------------------------
object compile_object (string filename)

// Compile an virtual object.
//
// Arguments:
//   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>.
// If the master returns 0, the usual 'Could not load'-error will occur.


//---------------------------------------------------------------------------
string get_wiz_name (string file)

// Return the author of a file.
//
// Arguments:
//   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 score errors
// to the right wizard.


//---------------------------------------------------------------------------
string printf_obj_name (object obj)

// Return a printable name for an object.
//
// Arguments:
//   obj: The object which name is of interest.
//
// Result:
//   A string with the objects name, or 0.
//
// This function is called by sprintf() to print a meaningful name
// in addition to the normal object_name().
// If this functions returns a string, the object will be printed
// as "<obj_name> (<printf_obj_name>)".


//---------------------------------------------------------------------------
mixed prepare_destruct (object obj)

// Prepare the destruction of the given object.
//
// Argument:
//   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.
// Furthermore, the function could notify the former inventory objects that
// their holder is under destruction (useful to move players out of rooms which
// are updated); and it could announce mudwide the destruction(quitting) of
// players.


//---------------------------------------------------------------------------
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.


//---------------------------------------------------------------------------
void receive_imp (string host, string msg, int port)

// Handle a received IMP message.
//
// Arguments:
//   host: Name of the host the message comes from.
//   msg : The received message.
//   port: the port number from which the message was sent.
//
// This function is called for every message received on the IMP port.


//---------------------------------------------------------------------------
void slow_shut_down (int minutes)

// Schedule a shutdown for the near future.
//
// Argument:
//   minutes: The desired time in minutes till the shutdown:
//             6, if just the user reserve has been put into use;
//             1, if the (smaller) system or even the 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. Don't take the 'minutes' as granted
// remaining uptime, just deduce the urgency of the shutdown from it.
// The delay is to give the players the opportunity to finish quests,
// sell their stuff, etc.
// It is possible that the driver may reallocate some memory after the
// function has been called, and then run again into a low memory situation,
// calling this function again.
//
// For example: this function might load an 'Armageddon' object and tells
// it what to do. It is the Armageddon object then which performs
// the shutdown.
//
// 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 before
// the mud shuts down the udp connections and the accepting socket for new
// players.
// The function has the opportunity to perform any cleanup operation, like
// informing the mudwho server that the mud is down. This can not be done
// when remove_player() is called because the udp connectivity is already
// gone then.


//===========================================================================
//  Error Handling
//
//===========================================================================

//---------------------------------------------------------------------------
void dangling_lfun_closure ()

// Handle a dangling lfun-closure.
//
// This is called when the gamedriver executes a closure using a vanished lfun.
// A proper handling is to raise a runtime error.
//
// Technical:
//   Upon replacing programs (see efun replace_program()), any existing
//   lambda closures of the object are adjusted to the new environment.
//   If a closure uses a lfun which vanished in the replacement process,
//   the reference to this lfun is replaced by a reference to this function.
//   The error will then occur when the execution of the adjusted lambda
//   reaches the point of the lfun reference.
//   There are two reasons for the delayed handling. First is that the
//   program replacement and with it the closure adjustment happens at
//   the end of a backend cycle, outside of any execution thread: noone
//   would see the error at this time.
//   Second, smart closures might know/recognize the program replacement
//   and skip the call to the vanished lfun.

{
  raise_error("dangling lfun closure\n");
}

//---------------------------------------------------------------------------
void log_error (string file, string err)

// Announce a compiler-time error.
//
// Arguments:
//   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.
// It should at least log the error in a file, and also announce it
// to the active player if it is an wizard.


//---------------------------------------------------------------------------
mixed heart_beat_error (object culprit, string err,
                        string prg, string curobj, int line)

// Announce an error in the heart_beat() function.
//
// Arguments:
//   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.
//
// This function has to announce an error in the heart_beat() function
// of culprit.
// At time of call, the heart_beat has been turned off.
// A player should at least get a "You have no heartbeat!" message, a more
// advanced handling would destruct the offending object and allow the
// heartbeat to restart.
//
// Note that <prg> denotes the program actually executed (which might be
// inherited one) whereas <curobj> is just the offending object.


//---------------------------------------------------------------------------
void runtime_error (string err, string prg, string curobj, int line)

// Announce a runtime error.
//
// Arguments:
//   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.
// If it is a wizard, it might give him the full error message together
// with the source line; if it is a player, it should issue a decent
// message ("Your sensitive mind notices a wrongness in the fabric of space")
// and could also announce the error to the wizards online.
//
// Note that <prg> denotes the program actually executed (which might be
// inherited one) whereas <curobj> is just the offending object.


//===========================================================================
//  Security and Permissions
//
// Most of these functions guard critical efuns. A good approach to deal
// with them is to redefine the efuns by simul_efuns (which can then avoid
// trouble prematurely) and give root objects only the permission to
// execute the real efuns.
//
// See also creator_file(), valid_read() and valid_write().
//===========================================================================

//---------------------------------------------------------------------------
int privilege_violation (string op, mixed who, mixed arg, mixed arg2)

// Validate the execution of a privileged operation.
//
// Arguments:
//   op   : the requestion operation (see below)
//   who  : the object requesting the operation (filename or object pointer)
//   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.
//   erq               : A the request <arg4> is to be send to the
//                       erq-demon by the object <who>.
//   execute_command   : Execute command string <arg2> for the object <arg>.
//   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     : The current object <who> renames object <arg>
//                       to name <arg2>.
//   send_imp          : 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>.
//   limited:          : Execute <arg> with reduced/changed limits.
//   set_limits        : Set limits to <arg>.
//   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_imp() 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.

//---------------------------------------------------------------------------
int query_allow_shadow (object victim)

// Validate a shadowing.
//
// Arguments:
//   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 function should deny shadowing on all root objects, else it might
// query the victim for clearance.


//---------------------------------------------------------------------------
int valid_trace (string what)

// Check if the player is allowed to use tracing.
//
// Argument:
//   what: The actual action (see below).
//
// Result:
//   Return 0 to disallow, any other value to allow it.
//
// Actions asked for so far are:
//   "trace":       Is the user allowed to use tracing?
//   "traceprefix": Is the user allowed to set a traceprefix?

//---------------------------------------------------------------------------
int valid_exec (string name, object ob, object obfrom)

// Validate the rebinding of an IP connection by usage of efun exec().
//
// Arguments:
//    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.
//    ob    : The object to receive the connection.
//    obfrom: The object giving the connection away.
//
// Result:
//   Return a non-zero number to allow the action,
//   any other value to disallow it.


//---------------------------------------------------------------------------
int valid_query_snoop (object obj)

// Validate if the snoopers of an object may be revealed by usage of the
// efun query_snoop().
//
// Arguments:
//   previous_object(): the asking object.
//   obj              : the object which snoopers are to be revealed.
//
// Result:
//   Return a non-zero number to allow the action,
//   any other value to disallow it.


//---------------------------------------------------------------------------
int valid_snoop (object snoopee, object snooper)

// Validate the start/stop of a snoop.
//
// Arguments:
//   snoopee: The victim of the snoop.
//   snooper: The wannabe snooper, or 0 when stopping a snoop.
//
// Result:
//   Return a non-zero number to allow the action,
//   any other value to disallow it.


//===========================================================================
//  Userids and depending Security
//
// For each object in the mud exists a string attribute which determines the
// objects rights in security-sensitive matters. In compat muds this attribute
// is called the "creator" of the object, in !compat muds the object's "userid"
// ("uid" for short).
//
// "Effective Userids" are an extension of this system, to allow the easier
// implementation of mudlib security by diffentiating between an objects
// theoretical permissions (uid) and its current permissions (euid) (some
// experts think that this attempt has failed (Heya Macbeth!)).
//
// The driver mainly implements the setting/querying of the (e)uids -- it is
// task of the mudlib to give out the right (e)uid to the right object, and
// to check them where necessary.
//
// If the driver is set to use 'strict euids', the loading and cloning
// of objects requires the initiating object to have a non-zero euid.
//
// The main use for (e)uids is for determination of file access rights, but
// you can of course use the (e)uids for other identification purposes as well.
//===========================================================================

//---------------------------------------------------------------------------
string get_bb_uid()

// Return the string (or 0) to be used as backbone-euid.
// It is just used by process_string() only if no this_object() is present.
// If strict-euids, the function must exist and return a string.

//---------------------------------------------------------------------------
int valid_seteuid (object obj, string neweuid)

// Validate the change of an objects euid by efun seteuid().
//
// Arguments:
//   obj    : The object requesting the new euid.
//   neweuid: The new euid requested.
//
// Result:
//   Return 1 to allow the change, any other value to disallow it.


//---------------------------------------------------------------------------
mixed valid_read  (string path, string euid, string fun, object caller)
mixed valid_write (string path, string euid, string fun, object caller)

// Validate a reading/writing file operation.
//
// Arguments:
//   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.
//   You can also return 1 to indicate that the path can be used unchanged.
//
// The path finally to be used must not contain spaces or '..'s .
//
// These are the central functions establishing the various file access
// rights.
//
// Note that this function is called in compat mode as well!
// If you need to be compatible with the old 2.4.5-mudlib, redirect these
// calls to the valid_read/valid_write in the player object.
//
// 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
//
// valid_write() is called for these operations:
//   ed_start     (when writing a file)
//   do_rename    (twice for each the old and new name)
//   mkdir
//   objdump
//   opcdump
//   save_object
//   remove_file
//   rmdir
//   write_bytes
//   write_file


//===========================================================================
//  ed() Support
//
//===========================================================================

//---------------------------------------------------------------------------
string make_path_absolute (string str)

// Absolutize a relative filename given to the editor.
//
// Argument:
//   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'.


//---------------------------------------------------------------------------
int save_ed_setup (object who, int code)

// Save individual settings of ed for a wizard.
//
// Arguments:
//   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 has to save the given integer into a safe place in the
// realm of the given wizard, either a file, or in the wizard itself.
//
// Be aware of possible security breaches: under !compat, a write_file()
// should be surrounded by a temporary setting of the masters euid to
// that of the wizard.


//---------------------------------------------------------------------------
int retrieve_ed_setup (object who)

// Retrieve individual settings of ed for a wizard.
//
// Arguments:
//   who : The wizard using the editor.
//
// Result:
//   The encoded options retrieved (0 if there are none).


//---------------------------------------------------------------------------
string get_ed_buffer_save_file_name (string file)

// Return a filename for the ed buffer to be saved into.
//
// Arguments:
//   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.


//===========================================================================
//  parse_command() Support  (!compat, SUPPLY_PARSE_COMMAND defined)
//
// 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 preference for the english language, so the
// the code for parsing english constructs is given as well.
//===========================================================================

//---------------------------------------------------------------------------
string *parse_command_id_list ()

// Return generic singular ids.

{
  return ({ "one", "thing" });
}


//---------------------------------------------------------------------------
string *parse_command_plural_id_list ()

// Return generic plural ids.

{
  return ({ "ones", "things", "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.

{
  return ({ "iffish" });
}


//---------------------------------------------------------------------------
string *parse_command_prepos_list ()

// Return common prepositions.

{
    return ({ "in", "on", "under", "behind", "beside" });
}


//---------------------------------------------------------------------------
string parse_command_all_word()

// Return the one(!) 'all' word.

{
  return "all";
}


/****************************************************************************/
