ds2.10/bin/
ds2.10/extra/
ds2.10/extra/crat/
ds2.10/extra/creremote/
ds2.10/extra/mingw/
ds2.10/extra/wolfpaw/
ds2.10/fluffos-2.16-ds05/
ds2.10/fluffos-2.16-ds05/Win32/
ds2.10/fluffos-2.16-ds05/compat/
ds2.10/fluffos-2.16-ds05/compat/simuls/
ds2.10/fluffos-2.16-ds05/include/
ds2.10/fluffos-2.16-ds05/testsuite/
ds2.10/fluffos-2.16-ds05/testsuite/clone/
ds2.10/fluffos-2.16-ds05/testsuite/command/
ds2.10/fluffos-2.16-ds05/testsuite/data/
ds2.10/fluffos-2.16-ds05/testsuite/etc/
ds2.10/fluffos-2.16-ds05/testsuite/include/
ds2.10/fluffos-2.16-ds05/testsuite/inherit/
ds2.10/fluffos-2.16-ds05/testsuite/inherit/master/
ds2.10/fluffos-2.16-ds05/testsuite/log/
ds2.10/fluffos-2.16-ds05/testsuite/single/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/compiler/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/efuns/
ds2.10/fluffos-2.16-ds05/testsuite/single/tests/operators/
ds2.10/fluffos-2.16-ds05/testsuite/u/
ds2.10/lib/cmds/admins/
ds2.10/lib/cmds/common/
ds2.10/lib/cmds/creators/include/
ds2.10/lib/daemon/services/
ds2.10/lib/daemon/tmp/
ds2.10/lib/doc/
ds2.10/lib/doc/bguide/
ds2.10/lib/doc/efun/all/
ds2.10/lib/doc/efun/arrays/
ds2.10/lib/doc/efun/buffers/
ds2.10/lib/doc/efun/compile/
ds2.10/lib/doc/efun/floats/
ds2.10/lib/doc/efun/functions/
ds2.10/lib/doc/efun/general/
ds2.10/lib/doc/efun/mixed/
ds2.10/lib/doc/efun/numbers/
ds2.10/lib/doc/efun/parsing/
ds2.10/lib/doc/help/classes/
ds2.10/lib/doc/help/races/
ds2.10/lib/doc/lfun/
ds2.10/lib/doc/lfun/all/
ds2.10/lib/doc/lfun/lib/abilities/
ds2.10/lib/doc/lfun/lib/armor/
ds2.10/lib/doc/lfun/lib/bank/
ds2.10/lib/doc/lfun/lib/bot/
ds2.10/lib/doc/lfun/lib/clay/
ds2.10/lib/doc/lfun/lib/clean/
ds2.10/lib/doc/lfun/lib/clerk/
ds2.10/lib/doc/lfun/lib/client/
ds2.10/lib/doc/lfun/lib/combat/
ds2.10/lib/doc/lfun/lib/connect/
ds2.10/lib/doc/lfun/lib/container/
ds2.10/lib/doc/lfun/lib/corpse/
ds2.10/lib/doc/lfun/lib/creator/
ds2.10/lib/doc/lfun/lib/daemon/
ds2.10/lib/doc/lfun/lib/damage/
ds2.10/lib/doc/lfun/lib/deterioration/
ds2.10/lib/doc/lfun/lib/donate/
ds2.10/lib/doc/lfun/lib/door/
ds2.10/lib/doc/lfun/lib/equip/
ds2.10/lib/doc/lfun/lib/file/
ds2.10/lib/doc/lfun/lib/fish/
ds2.10/lib/doc/lfun/lib/fishing/
ds2.10/lib/doc/lfun/lib/flashlight/
ds2.10/lib/doc/lfun/lib/follow/
ds2.10/lib/doc/lfun/lib/ftp_client/
ds2.10/lib/doc/lfun/lib/ftp_data_connection/
ds2.10/lib/doc/lfun/lib/fuel/
ds2.10/lib/doc/lfun/lib/furnace/
ds2.10/lib/doc/lfun/lib/genetics/
ds2.10/lib/doc/lfun/lib/holder/
ds2.10/lib/doc/lfun/lib/id/
ds2.10/lib/doc/lfun/lib/interactive/
ds2.10/lib/doc/lfun/lib/lamp/
ds2.10/lib/doc/lfun/lib/leader/
ds2.10/lib/doc/lfun/lib/light/
ds2.10/lib/doc/lfun/lib/limb/
ds2.10/lib/doc/lfun/lib/living/
ds2.10/lib/doc/lfun/lib/load/
ds2.10/lib/doc/lfun/lib/look/
ds2.10/lib/doc/lfun/lib/manipulate/
ds2.10/lib/doc/lfun/lib/meal/
ds2.10/lib/doc/lfun/lib/messages/
ds2.10/lib/doc/lfun/lib/player/
ds2.10/lib/doc/lfun/lib/poison/
ds2.10/lib/doc/lfun/lib/position/
ds2.10/lib/doc/lfun/lib/post_office/
ds2.10/lib/doc/lfun/lib/potion/
ds2.10/lib/doc/lfun/lib/room/
ds2.10/lib/doc/lfun/lib/server/
ds2.10/lib/doc/lfun/lib/spell/
ds2.10/lib/doc/lfun/lib/torch/
ds2.10/lib/doc/lfun/lib/vendor/
ds2.10/lib/doc/lfun/lib/virt_sky/
ds2.10/lib/doc/lfun/lib/weapon/
ds2.10/lib/doc/lfun/lib/worn_storage/
ds2.10/lib/doc/lpc/constructs/
ds2.10/lib/doc/lpc/etc/
ds2.10/lib/doc/lpc/intermediate/
ds2.10/lib/doc/lpc/types/
ds2.10/lib/doc/misc/
ds2.10/lib/doc/old/
ds2.10/lib/doc/phints/
ds2.10/lib/domains/
ds2.10/lib/domains/Praxis/adm/
ds2.10/lib/domains/Praxis/attic/
ds2.10/lib/domains/Praxis/cemetery/mon/
ds2.10/lib/domains/Praxis/data/
ds2.10/lib/domains/Praxis/death/
ds2.10/lib/domains/Praxis/mountains/
ds2.10/lib/domains/Praxis/obj/armour/
ds2.10/lib/domains/Praxis/obj/magic/
ds2.10/lib/domains/Praxis/obj/weapon/
ds2.10/lib/domains/Praxis/orc_valley/
ds2.10/lib/domains/Ylsrim/
ds2.10/lib/domains/Ylsrim/adm/
ds2.10/lib/domains/Ylsrim/armor/
ds2.10/lib/domains/Ylsrim/broken/
ds2.10/lib/domains/Ylsrim/fish/
ds2.10/lib/domains/Ylsrim/meal/
ds2.10/lib/domains/Ylsrim/npc/
ds2.10/lib/domains/Ylsrim/obj/
ds2.10/lib/domains/Ylsrim/virtual/
ds2.10/lib/domains/Ylsrim/weapon/
ds2.10/lib/domains/alpha/room/
ds2.10/lib/domains/alpha/virtual/
ds2.10/lib/domains/campus/adm/
ds2.10/lib/domains/campus/etc/
ds2.10/lib/domains/campus/meals/
ds2.10/lib/domains/campus/txt/ai/charles/
ds2.10/lib/domains/campus/txt/ai/charles/bak2/
ds2.10/lib/domains/campus/txt/ai/charles/bak2/bak1/
ds2.10/lib/domains/campus/txt/ai/charly/
ds2.10/lib/domains/campus/txt/ai/charly/bak/
ds2.10/lib/domains/campus/txt/jenny/
ds2.10/lib/domains/cave/doors/
ds2.10/lib/domains/cave/etc/
ds2.10/lib/domains/cave/meals/
ds2.10/lib/domains/cave/weap/
ds2.10/lib/domains/default/chamber/
ds2.10/lib/domains/default/creator/
ds2.10/lib/domains/default/doors/
ds2.10/lib/domains/default/etc/
ds2.10/lib/domains/default/vehicle/
ds2.10/lib/domains/default/virtual/
ds2.10/lib/domains/town/save/
ds2.10/lib/domains/town/txt/shame/
ds2.10/lib/domains/town/virtual/
ds2.10/lib/domains/town/virtual/bottom/
ds2.10/lib/domains/town/virtual/space/
ds2.10/lib/estates/
ds2.10/lib/ftp/
ds2.10/lib/lib/comp/
ds2.10/lib/lib/daemons/
ds2.10/lib/lib/daemons/include/
ds2.10/lib/lib/lvs/
ds2.10/lib/lib/user/
ds2.10/lib/lib/virtual/
ds2.10/lib/log/
ds2.10/lib/log/adm/
ds2.10/lib/log/archive/
ds2.10/lib/log/chan/
ds2.10/lib/log/errors/
ds2.10/lib/log/law/adm/
ds2.10/lib/log/law/email/
ds2.10/lib/log/law/names/
ds2.10/lib/log/law/sites-misc/
ds2.10/lib/log/law/sites-register/
ds2.10/lib/log/law/sites-tempban/
ds2.10/lib/log/law/sites-watch/
ds2.10/lib/log/open/
ds2.10/lib/log/reports/
ds2.10/lib/log/router/
ds2.10/lib/log/secure/
ds2.10/lib/log/watch/
ds2.10/lib/obj/book_source/
ds2.10/lib/obj/include/
ds2.10/lib/powers/prayers/
ds2.10/lib/powers/spells/
ds2.10/lib/realms/template/
ds2.10/lib/realms/template/adm/
ds2.10/lib/realms/template/area/
ds2.10/lib/realms/template/area/armor/
ds2.10/lib/realms/template/area/npc/
ds2.10/lib/realms/template/area/obj/
ds2.10/lib/realms/template/area/room/
ds2.10/lib/realms/template/area/weap/
ds2.10/lib/realms/template/bak/
ds2.10/lib/realms/template/cmds/
ds2.10/lib/save/kills/o/
ds2.10/lib/secure/cfg/classes/
ds2.10/lib/secure/cmds/builders/
ds2.10/lib/secure/cmds/creators/include/
ds2.10/lib/secure/cmds/players/include/
ds2.10/lib/secure/daemon/imc2server/
ds2.10/lib/secure/daemon/include/
ds2.10/lib/secure/lib/
ds2.10/lib/secure/lib/include/
ds2.10/lib/secure/lib/net/include/
ds2.10/lib/secure/lib/std/
ds2.10/lib/secure/log/adm/
ds2.10/lib/secure/log/bak/
ds2.10/lib/secure/log/intermud/
ds2.10/lib/secure/log/network/
ds2.10/lib/secure/modules/
ds2.10/lib/secure/npc/
ds2.10/lib/secure/obj/include/
ds2.10/lib/secure/room/
ds2.10/lib/secure/save/
ds2.10/lib/secure/save/backup/
ds2.10/lib/secure/save/boards/
ds2.10/lib/secure/save/players/g/
ds2.10/lib/secure/tmp/
ds2.10/lib/secure/upgrades/files/
ds2.10/lib/secure/verbs/creators/
ds2.10/lib/std/board/
ds2.10/lib/std/lib/
ds2.10/lib/verbs/admins/include/
ds2.10/lib/verbs/builders/
ds2.10/lib/verbs/common/
ds2.10/lib/verbs/common/include/
ds2.10/lib/verbs/creators/
ds2.10/lib/verbs/creators/include/
ds2.10/lib/verbs/rooms/
ds2.10/lib/verbs/rooms/include/
ds2.10/lib/www/client/
ds2.10/lib/www/errors/
ds2.10/lib/www/images/
ds2.10/win32/
/*    /secure/daemon/master.c
 *    from the Dead Souls LPC Library
 *    the master object, responsible for security
 *    created by Descartes of Borg 940910
 *    error handling by Beek@The Idea Exchange 941004
 *    Version: @(#) master.c 1.7@(#)
 *    Last modified: 96/12/14
 */

#include <runtime_config.h>
#include ROOMS_H
#include <cfg.h>
#include <lib.h>
#include <objects.h>
#include <privs.h>
#include <dirs.h>
#include <save.h>
#include <daemons.h>
#include <commands.h>
#include NETWORK_H
#include <parser_error.h>
#include <message_class.h>
#include <function.h>
#include "master.h"

#ifndef COMPAT_MODE
#define COMPAT_MODE 1
#endif
#ifndef DEFAULT_PARSING
#define DEFAULT_PARSING 1
#endif
#ifndef RESET_ALL
#define RESET_ALL 1
#endif
#ifndef MAX_SINGLE_OBJECT
#define MAX_SINGLE_OBJECT        4000
#endif
#ifndef CONSOLE_TRACE
#define CONSOLE_TRACE 0
#endif

inherit LIB_DAEMON;
#include <mssp.h>

private static int incept_date, ResetNumber, heart_count, in_reset;
private static int eval_threshold, reset_handle = -1;
private int BootScore, PerformanceScore, globalpmsg;
private static object Unguarded, gguy;
private static string PlayerName, rlog, gcmd, bname, gstr;
private static object NewPlayer;
private static mapping Groups, ReadAccess, WriteAccess, CostErr;
private static string *ParserDirs = ({ "secure", "verbs", "daemon", "lib", "powers" });
private static string array efuns_arr = ({});
private static string MudName, mconfig;

static void Setup(){
    if(uptime() < 30) MudName = 0;
}

void create() {
#ifdef __OPCPROF__
    string tmpfun, junk, opstr;
    string *oparr = ({});
    string opfile = "/tmp/opc";
    opcprof(opfile);
    if(file_exists(opfile+".efun")){
        opstr = read_file(opfile+".efun");
        if(opstr){ 
            oparr = explode(opstr, "\n");
        }
        if(sizeof(oparr)){
            foreach(string element in oparr){
                if(sscanf(element,"%s %s",tmpfun, junk) == 2){
                    if(tmpfun[0..0] == "_") tmpfun = tmpfun[1..];
                    efuns_arr += ({ tmpfun });
                }
            }
        }
    }
#endif
    eval_threshold = (get_config(__MAX_EVAL_COST__) / 1000000) + 1;
    incept_date = time();
    BootScore = 0;
    this_object()->GetPerformanceScore();
    Unguarded = 0;
    NewPlayer = 0;
    PlayerName = 0;
    ResetNumber = 1;
    if(!(file_exists("/secure/sefun/native_version.c"))){
        cp("/secure/scripts/native_version.proto", 
                "/secure/sefun/native_version.c");
    }
    new_read();
    new_write();
    new_groups();
    reset_handle = call_out( (: eventReset :), TIME_TO_RESET );
    call_out( (: Setup :), 10);
    set_heart_beat(1);
    ReadName();
}

static void heart_beat(){
    heart_count++;
    if(!(heart_count % 60)){
        CostErr = ([]);
        if(in_reset){
            eventReset();
        }
    }
    if(heart_count > 64000) heart_count = 0;
}

void new_read() {
    mapping tmp;
    tmp = ([]);
    load_access(CFG_READ, tmp);
    ReadAccess = tmp;
}

void new_write() {
    mapping tmp;
    tmp = ([]);
    load_access(CFG_WRITE, tmp);
    WriteAccess = tmp;
}

void new_groups() {
    mapping tmp;
    tmp = ([]);
    load_access(CFG_GROUPS, tmp);
    Groups = tmp;
}

private static void load_access(string cfg, mapping resource) {
    string *lines;
    string file;

    if( !(file = read_file(cfg)) ) {
        error("Failed to find config file: "+cfg);
    }
    lines = filter(explode(file, "\n"), function(string line) {

            if( !line || trim(line) == "" ) {
            return 0;
            }
            if( line[0] == '#' ) {
            return 0;
            }
            return 1;
            });
    foreach(string line in lines) {
        string fl, ac = "";

        if( sscanf(line, "(%s)%s", fl, ac) != 2 ) {
            error("Error in loading config file " + cfg + ".");
        }
        ac = trim(ac);
        if(last(fl,1) == "*" && last(fl,2) != "/*"){
            string camino = (path_prefix(fl) || "");
            string targ = truncate(replace_string(fl, camino, ""), 1);
            string *pool = get_dir(camino+"/");
            string *targs;
            if(sizeof(targ)) targ = targ[1..];
            targs = regexp(pool,"^"+targ);
            pool = ({});
            foreach(string element in targs){
                pool += ({ camino + "/" + element });
            }
            foreach(string element in pool){
                if(sizeof(element)) resource[element] = explode(ac, ":");
            }
        }
        else if(last(fl,3) == "/*/"){
            string tmp = truncate(fl,2);
            foreach(string element in get_dir(tmp)){
                resource[tmp+element+"/"] = explode(ac, ":");
            }
        }
        else resource[fl] = explode(ac, ":");
    }
}

void flag(string str) {
    string file, arg;
    int i, x;

    if(previous_object()) return;
    if(sscanf(str, "for %d", x) == 1) {
        for(i=0; i<x; i++) {}
        return;
    }
    if(sscanf(str, "call %s %s", file, arg)) {
        write("Got "+call_other(file, arg)+" back.\n");
        return;
    }
    write("Master: unknown flag.\n");
}

string *epilog(int nopreload) {
    string *lines, *files;
    string content;
    int i;

    if(nopreload || !(content = read_file(CFG_PRELOAD))) return ({});
    i = sizeof(lines = explode(content, "\n"));
    files = ({});
    while(i--) {
        if(!lines[i] || lines[i] == "" || lines[i][0] == '#') continue;
        files += ({ lines[i] });
    }
    return files;
}

string privs_file(string file) {
    string tmp, nom = 0;
    mixed ret;
    if( !strsrch(file, DIR_PLAYERS) ) sscanf(file, DIR_PLAYERS "/%*s/%s",tmp);
    else if( !strsrch(file, DIR_CRES) ) sscanf(file, DIR_CRES "/%*s/%s",tmp);
    if(tmp && grepp(tmp, ".")) nom = cleaned_name(tmp);
    else nom = tmp;
    if( nom ) {
        if(!grepp(file,".")) file += ".";
        if(!strsrch(file, DIR_CRES + "/" + nom[0..0] + "/" + nom + ".")){
            string str, grp;

            str = nom;
            foreach( grp in keys(Groups) )
                if( member_array(nom, Groups[grp]) != -1) str = str + ":" + grp;
            ret = str;
        }
        else if( !strsrch(file, DIR_PLAYERS + "/" + nom[0..0] + 
                    "/" + nom + "."))
            ret = nom;
        else ret = 0;
    }
    if(undefinedp(ret)) ret = file_privs(file);
    return ret;
}

void preload(string str) {
    string err;
    mapping before, after;
    int t;
#ifdef __HAS_RUSAGE__
    before = rusage();
#endif
    if( !file_exists(str = lpc_file(str)) ) return;
    write("Preloading: " + str + "...");

    if( err = catch(call_other(str, "???")) ){
        write("\nGot error "+err+" when loading "+str+".\n");
    }
    else {
#ifdef __HAS_RUSAGE__
        after = rusage();
        if(sizeof(before) && sizeof(after)){
            t = after["utime"] - before["utime"];
            BootScore += t;
            write("("+t+"ms)\n");
        }            
        return;
#endif
        write("(done)\n");
    }
}

int valid_write(string file, object ob, string fun) {
    string *ok;
    int ret;
    if( ob == master() ) ret = 1;
    ok = match_path(WriteAccess, file);
    if(!ret) ret = check_access(ob, fun, file, ok, "write");
    return ret;
}

int valid_read(string file, object ob, string fun) {
    string *ok;
    int ret;
    if( ob == master() ) ret = 1;
    ok = match_path(ReadAccess, file);
    if(!ret) ret = check_access(ob, fun, file, ok, "read");
    return ret;
}

int valid_link(string from, string to) {
    object ob = previous_object();
    if(!interactive(ob)) ob = previous_object(1);
    if(!interactive(ob)) ob = previous_object(2);
    if(!interactive(ob)) ob = previous_object(3);
    if(!interactive(ob)) {return 0;}
    if(ob->GetForced()) { tell_player(ob,"Someone's fucking with you."); return 0;}
    if(!valid_write(from, ob, "link")) {return 0;}
    if(!valid_write(to, ob, "link")) {return 0;}
    return 1;
}

int valid_apply(string *ok) {
    int ret;
    ret = check_access(previous_object(1),0,previous_object(0), ok, "apply");
    return ret;
}

int check_access(object ob, string fun, mixed file, string *ok, string oper) {
    object *stack;
    string *privs;
    string priv, tmp;
    int i;

    if( objectp(file) ) tmp = base_name(file);
    if(tmp) file = tmp;
    if( ok && sizeof(ok) && ok[0] == "all" ) return 1;
    if( Unguarded == ob ){
        tmp = base_name(ob);
        if( tmp == LIB_PLAYER || tmp == LIB_CREATOR){
            string sfilep, sfilec;
            sfilep = DIR_PLAYERS+"/"+PlayerName[0..0]+"/"+ PlayerName + __SAVE_EXTENSION__;
            sfilec = DIR_CRES+"/"+PlayerName[0..0]+"/"+ PlayerName + __SAVE_EXTENSION__;
            if( !PlayerName ) i = sizeof(stack = ({ob})+previous_object(-1));
            else if( file == sfilep ) return 1;
            else if( file == sfilec ) return 1;
#if ENABLE_INSTANCES
            else if( file == new_savename(sfilep) ){
                return 1;
            }
            else if( file == new_savename(sfilec) ){
                return 1;
            }
#endif
            else i = sizeof(stack = ({ ob }));
        }
        else if( tmp == file ) return 1;
        else if( tmp + __SAVE_EXTENSION__ == file ) return 1;
#if ENABLE_INSTANCES
        else if( new_savename(tmp) == file ) return 1;
#endif
        else i = sizeof(stack = ({ ob }));
    }
    else if(Unguarded && base_name(ob) == SEFUN) {
        if(Unguarded == previous_object(1))
            stack = ({ previous_object(1) });
        else stack = ({ ob }) + previous_object(-1);
    }
    else i = sizeof(stack = previous_object(-1) + ({ ob }));
    while(i--) {
        if(!stack[i] || stack[i] == this_object()) {
            continue;
        }
        if(file_name(stack[i]) == SEFUN) {
            continue;
        }
        if(!(priv = query_privs(stack[i]))) {
            if(false()){
                debug_message("\nSPLAT 1: "+identify(stack[i]));
            }    
            return 0;
        }
        if(!ok && oper == "read") {
            continue;
        }
        privs = explode(priv, ":");
        if(member_array(PRIV_SECURE, privs) != -1) {
            continue;
        }
        if(stringp(file) && member_array(file_privs(file), privs) != -1) {
            continue;
        }
        if(!ok && oper == "write") {
            if(userp(stack[i]) && check_user(stack[i], fun, file, oper)){
                continue;
            }
            else {
                if(false()) debug_message("\nSPLAT 2\n");
                return 0;
            }
        }
        if(sizeof(privs & ok)) {
            continue;
        }
        if(userp(stack[i]) && check_user(stack[i], fun, file, oper)) continue;
        if(userp(stack[i]) && check_domain(stack[i], fun, file,oper)) continue;
        return 0;
    }
    return 1;
}

nomask static int check_user(object ob, string fun, string file, string oper){
    string nom, tmp;
    int x;
    if(interactive(ob) && !creatorp(ob)){
        nom = ob->GetKeyName();
        if(!strsrch(file,DIR_ESTATES + "/"+nom[0..0]+"/"+nom)) return 1;
    }
    if( !sscanf(file, REALMS_DIRS "/%s", nom) ) return 0;
    if( sscanf(nom, "%s/%*s", tmp) ) nom = tmp;
    nom = user_path(nom)+"adm/access";
    if(strsrch(nom,"/tmp") && file_size(nom+".c") > 0)
        catch(x = call_other(nom, "check_access", ob, fun, file, oper));
    return x;
}

nomask static int check_domain(object ob, string fun, string file, string o) {
    string nom;
    int x;
    if( !sscanf(file, DOMAINS_DIRS+"/%s/%*s", nom) ) return 0;
    nom = DOMAINS_DIRS+"/"+nom+"/adm/access";
    if(file_size(nom+".c") < 0) return 0;
    catch(x = call_other(nom, "check_access", ob, fun, file, o));
    return x;
}

object connect(int port) {
    object ob;
    string err;
    string file;

    file = LIB_CONNECT;
    if( err  = catch(ob = new(file)) ) {
        write("It looks like someone is working on the user object.\n");
        write(err);
        destruct(ob);
    }
    return ob;
}

object compile_object(string str) {
    string nom, tmp, where, which, sfile;
    object ob;
    sfile = str+__SAVE_EXTENSION__;
    if(sscanf(str, REALMS_DIRS+"/%s/%*s", nom))
        tmp = sprintf("%svirtual/server", user_path(nom));
    else if(sscanf(str, DOMAINS_DIRS+"/%s/%*s", nom))
        tmp = sprintf("%s/%s/virtual/server", DOMAINS_DIRS, nom);
    else if(strsrch(str, ESTATES_DIRS) == 0)
        tmp = sprintf("%s/virtual/server", ESTATES_DIRS);
    else if(sscanf(str, DIR_PLAYERS+"/%*s/%s", nom)) {
        if(!NewPlayer){
            return 0;
        }
#if ENABLE_INSTANCES
        nom = old_savename(nom);
#endif
        if(last(nom,2) == ".o") nom = truncate(nom, 2);
        if(last(sfile,4) == ".o.o") sfile = truncate(sfile, 2);
        if(NewPlayer->GetKeyName() != nom) return 0;
        PlayerName = nom;
        ob = new(LIB_PLAYER);
        if(file_exists(sfile) || file_exists(new_savename(sfile))){ 
            ob->restore_player(nom);
        }
        else {
            if(file_size(DIR_PLAYERS) != -2) mkdir(DIR_PLAYERS);
        }
        if(file_size(DIR_PLAYERS+"/"+nom[0..0]) != -2)
            mkdir(DIR_PLAYERS+"/"+nom[0..0]);
        ob->SetKeyName(nom);
        PlayerName = 0;
        return ob;
    }
    else if( sscanf(str, DIR_CRES+"/%*s/%s", nom) ) {
        if(!NewPlayer) return 0;
#if ENABLE_INSTANCES
        nom = old_savename(nom);
        if(last(nom,2) == ".o") nom = truncate(nom, 2);
#endif
        if(last(sfile,4) == ".o.o") sfile = truncate(sfile, 2);
        if(NewPlayer->GetKeyName() != nom) return 0;
        PlayerName = nom;
        ob = new(LIB_CREATOR);
        if(file_exists(sfile) || file_exists(new_savename(sfile))){
            ob->restore_player(nom);
        }
        else {
        }
        ob->SetKeyName(nom);
        PlayerName = 0;
        return ob;
    }
    if(file_size(tmp+".c") < 0) {
        if(sscanf(str, "%s.%s", where, which) != 2) return 0;
        if(sscanf(str, REALMS_DIRS+"/%s/%*s", nom))
            tmp = sprintf("%svirtual/%s_server", user_path(nom), which);
        else if(sscanf(str, DOMAINS_DIRS+"/%s/%*s", nom))
            tmp = sprintf("%s/%s/virtual/%s_server", DOMAINS_DIRS, nom, which);
        if(file_size(tmp+".c") < 0) return 0;
        else return call_other(tmp, "compile_object", where);
    }
    return call_other(tmp, "compile_object", str);               
}

static void crash(mixed args...) {
    string err;
    string guilty_stack = get_stack(1);
    string guilty_obs = identify(previous_object(-1));
    if(sizeof(args)) err = args[0];
    write_file(DIR_LOGS "/crashes",
            mud_name() + " crashed " + ctime(time()) + " with error " +
            err+".\n"+guilty_stack+"\n"+guilty_obs+"\n---\n");
    message("system", "Reality implosion!!!  Everyone duck!!!", users());
    message("system", "You are being forced to quit.", users());
    users()->cmdQuit();
}

int valid_bind(object binder, object old_owner, object new_owner) {
    int ret;
    mixed privs;
    if(!binder) ret = 0;
    else if( binder == this_object() ) ret = 1;
    else if( base_name(binder) == SEFUN ) ret = 1;
    else if( member_array(PRIV_SECURE, 
                explode((privs = query_privs(binder)), ":")) != -1 ) ret = 1;
    return ret;
}

int valid_hide(object who) {
    string priv;
    if(!objectp(who)) return 0;
    if(environment(who) && hiddenp(environment(who))) return 1;
    if(!(priv = query_privs(who))) return 0;
    else return (member_array(PRIV_SECURE, explode(priv, ":")) != -1);
}

int valid_override(string file, string nom){ 
    return (file == SEFUN);
}

int valid_save_binary(string str) { return 1; }

int valid_shadow(object ob) {
    object targ = previous_object();
    return (!virtualp(targ) && !strsrch(file_name(targ), DIR_SHADOWS));
}

int valid_object(object ob) {
    string file, contents;
    file = file_name(ob);
    contents = read_file(base_name(ob)+".c");
    if(!contents) contents = "";
    if(strsrch(contents,"parse_add_rule") != -1 
            || strsrch(contents, "SetRules") != -1) {
        string prefix;
        if(!sscanf(file,"/%s/%*s",prefix)) return 0;
        if(member_array(prefix, ParserDirs) == -1) return 0;
    }
    if( !strsrch(file, DIR_TMP) ) return 0;
    else if( !strsrch(file, DIR_FTP) ) return 0;
    else if( !strsrch(file, DIR_LOGS) ) return 0;
    else if( !strsrch(file, DIR_SECURE_SAVE) ){
        return 0;
    }
    else return 1;
}

int valid_socket(object ob, string fun, mixed *info) {
    object *obs;
    int port;
    string tmp;
    int i;
    if( info && sizeof(info) == 4 ) {
        ob = info[1];
        port = info[3];
        if( port == PORT_ADMIN && ob != find_object(ADMIN_D) ) {
            return 0;
        }
        if( port == PORT_RCP && ob != find_object(REMOTE_D) ) {
            return 0;
        }
    }
    i = sizeof(obs = previous_object(-1));
    while(i--) {
        if( !obs[i] ) continue;
        if( userp(obs[i]) ) continue;
        tmp = query_privs(obs[i]);
        if(!tmp && base_name(obs[i]) == SEFUN) tmp = "SECURE";
        if( !(tmp) ) return 0;
        if( !sizeof(explode(tmp, ":") &
                    ({ PRIV_SECURE, PRIV_MUDLIB, PRIV_CMDS, PRIV_GENERAL })) ){
            return 0;
        }
    }
    return 1;
}

mixed apply_unguarded(function f) {
    object previous_unguarded;
    string err;
    mixed val;

    if(!f || !functionp(f)){
        error("Invalid function passed.");
        return 0;
    }

    if((functionp(f) & FP_OWNER_DESTED)){
        error("Function owner dested: invalid function.");
        return 0;
    }

    if(base_name(previous_object(0)) != SEFUN) {
        error("Illegal unguarded apply.");
        return 0;
    }
    previous_unguarded = Unguarded;
    Unguarded = previous_object(1);
    err = catch(val = evaluate(f) );
    Unguarded = previous_unguarded;
    if(err) error(err);
    return val; 
}

string error_handler(mapping mp, int caught) {
    string ret, file, dbg;
    int now = time();

    if(!CostErr) CostErr = ([ now : 0 ]);
    else if(undefinedp(CostErr[now])) CostErr[now] = 0;

    if(CONSOLE_TRACE){
        dbg = "\n----\n";
        foreach(mixed key, mixed val in mp){
            dbg += identify(key) + " : "+identify(val)+"\n";
        }
        dbg += "\n----\n";
        debug_message(dbg);
    }
    if(mp && mp["error"]){
        if(grepp(mp["error"], "Too deep recursion")){
            debug_message("Too deep recursion\n"+get_stack());
        }
        if(grepp(mp["error"], "Too many open files")){
            debug_message("Too many open files!\n");
            shutdown(-9);
        }
        if(grepp(mp["error"], "Too long evaluation.")){
            CostErr[now]++; 
        }
        if(grepp(mp["error"], "Can't catch eval cost too big error.")){
            CostErr[now]++;
        }
        if(CostErr[now] >= eval_threshold){
            /* This prevents a strange eval cost cascade that
             * can sometimes happen under extreme load. Unfortunately
             * the only effective countermeasure is a hard reboot
             * of the mud.
             */
            debug_message("Eval cost error cascade!\n");
            shutdown(-9);
        }
    }
    ret = "---\n"+timestamp()+"\n"+ standard_trace(mp);
    if( caught ) write_file(file = "/log/catch", ret);
    else write_file(file = "/log/runtime", ret);
    if( this_player(1) && find_object(SEFUN) ) {
        this_player(1)->SetLastError(mp);
        if( creatorp(this_player(1)) ) {
            this_player(1)->eventPrint(ret + "Trace written to " + file,
                    MSG_SYSTEM);
        }
        else {
            if( !strsrch(file_name(this_player(1)), LIB_CONNECT) ) {
                return "/log/login\n"+standard_trace(mp)+"\n--\n";
            }
            this_player()->eventPrint("A runtime error occurred.");
            CHAT_D->eventSendChannel("System", "error", "A runtime error "
                    "occurred to " + 
                    this_player(1)->GetCapName()+".");
            rlog = "-----\n" +timestamp()+ ": "+this_player(1)->GetCapName()+"\n";
            rlog += load_object("/secure/cmds/creators/dbxwhere")->cmd(this_player(1)->GetKeyName());
            rlog += flat_map(this_player()->GetLastError())+"\n-----\n";
            unguarded( (: write_file("/log/player_errors", rlog) :) );
        }
    }
    return 0;
}

void log_error(string file, string msg) {
    string nom, tmp, tmp2;

    if( file[0] != '/' ) {
        file = "/" + file;
    }
    if(!this_player()){
        object *object_stack = call_stack(1);
        object web_sessions = load_object(WEB_SESSIONS_D);
        if(web_sessions && member_array(web_sessions, object_stack) != -1){
            web_sessions->ReceiveErrorReport(msg);
        }
    }
    if( sscanf(file, REALMS_DIRS+"/%s/%s", nom, tmp) != 2 && 
            sscanf(file, DOMAINS_DIRS+"/%s/%s", nom, tmp) != 2 && 
            sscanf(file, ESTATES_DIRS+"/%s/%s/%s", tmp, nom, tmp2) != 3 ) 
        sscanf(file, "/%s/%s", nom, tmp);
    if( !nom ) nom = "log";
    catch(write_file(DIR_ERROR_LOGS "/" + nom, timestamp()+" "+msg));
    if(msg && this_player(1) && builderp(this_player(1))){
        catch(tell_player(this_player(1),msg));
    }
}

varargs string standard_trace(mapping mp, int flag) {
    string ret;
    mapping *trace;
    int i,n;

    ret = mp["error"] + "Object: " + 
        trace_line(mp["object"], mp["program"], mp["file"], mp["line"]);
    ret += "\n";
    trace = mp["trace"];
    n = sizeof(trace);
    for (i=0; i<n; i++) {
        if( flag ) ret += sprintf("#%d: ", i);
        ret += sprintf("'%s' at %s", trace[i]["function"], 
                trace_line(trace[i]["object"], trace[i]["program"], 
                    trace[i]["file"], trace[i]["line"]));
    }
    return ret;
}

string trace_line(object obj, string prog, string file, int line) {
    string ret;
    string objfn = obj ? file_name(obj) : "<none>";

    ret = objfn;
    if( different(objfn, prog) ) ret += sprintf(" (%s)", prog);
    if( file != prog ) ret += sprintf(" at %s:%d\n", file, line);
    else ret += sprintf(" at line %d\n", line);
    return ret;
}

int different(string fn, string pr) {
    int tmp;
    sscanf(fn, "%s#%d", fn, tmp);
    fn += ".c";
    return (fn != pr) && (fn != ("/" + pr));
}

void master_log_file(string file, string msg) {
    if(file_name(previous_object()) != SEFUN) return;
    if(file_size(file) > MAX_LOG_SIZE){
        string pre = path_prefix(file);
        string post = replace_string(file, pre + "/", "");
        write_file(file,"\nEND-OF-LOG\n");
        if(!directory_exists(pre + "/archive")){
            mkdir(pre + "/archive");
        }
        rename(file, pre + "/archive/" + post + "-" + timestamp());
    }
    write_file(file, msg);
}

string make_path_absolute(string file) {
    return absolute_path(this_player(1)->query_cwd(), file);
}

int player_exists(string nom) {
    string sfilec, sfilep;
    if( !nom ) return 0;
    sfilec = DIR_CRES "/" + nom[0..0] + "/" + nom + __SAVE_EXTENSION__;
    sfilep = DIR_PLAYERS "/" + nom[0..0] + "/" + nom + __SAVE_EXTENSION__;
#if ENABLE_INSTANCES
    sfilep = new_savename(sfilep);
    sfilec = new_savename(sfilec);
#endif
    if(unguarded((: file_exists, sfilec :))) return 1;
    if(unguarded((: file_exists, sfilep :))) return 1;
    return 0;
}

string domain_file(string str) {
    string nom, tmp;
    if(sscanf(str, DOMAINS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    return 0;
}

string author_file(string str) {
    string nom, tmp, tmp2;

    if(sscanf(str, REALMS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    else if(sscanf(str, ESTATES_DIRS+"/%s/%s/%s", tmp, nom, tmp2) == 3) return nom;
    return 0;
}

static int slow_shutdown() {
    write_file(DIR_LOGS "/audit", 
            "Armageddon loaded by master: "+ctime(time())+".\n");
    EVENTS_D->eventRebootMud(2);
    return 1;
}

int save_ed_setup(object who, int code) {
    string file;

    if(!intp(code)) return 0;
    rm(file = user_path(who->GetKeyName())+".edrc");
    return write_file(file, code+"");
}

int retrieve_ed_setup(object who) {
    string file;

    file = user_path(who->GetKeyName())+".edrc";
    if(!file_exists(file)) return 0;
    return to_int(read_file(file));    }

    string get_save_file_name() {
        mixed str;

        if(!this_player(1)) return DIR_TMP+"/.dead.edit";
        str = this_player(1)->GetKeyName();
        if(!str || !stringp(str)) return DIR_TMP+"/.dead.edit";
        if(file_size(user_path(str)) == -2)
            return user_path(str)+"dead.edit";
        else return DIR_TMP+"/"+str+".dead.edit";
    }

int is_locked() { return MUD_IS_LOCKED; }

string *parse_command_id_list() { return ({ "one", "thing" }); }

string *parse_command_plural_id_list() { return ({ "ones", "things","them"}); }

string *parse_command_adjectiv_id_list() {
    return ({ "the", "an", "a" });
}

string *parse_command_prepos_list() {
    return ({ "in", "with", "without", "into", "for", "on", "under", "against",
            "out", "within", "of", "from", "between", "at", "to", "over", "near",
            "inside", "onto", "off", "through", "across", "up", "down", "every",
            "around", "about", "only", "here", "room", "exit", "enter", "-r", "-a"});
}

string parse_command_all_word() { return "all"; }

string parser_error_message(int type, object ob, mixed arg, int flag) {
    string err;
    object tmpob;
    if( ob ) err = ob->GetShort();
    else err = "";
    switch(type) {
        string wut;
        object wat;

        case 0:
        if(arg && objectp(arg)) wat = arg;
        if(!wat && arg && arrayp(arg) && sizeof(arg)){
            foreach(mixed element in arg){
                if(objectp(element)) wat = element;
            }
        }
        if(ob && wat){
            err = "You can't use "+ob->GetShort()+" with "+
                wat->GetShort()+" that way.";
        }
        else if(ob){
            err = "It seems you can't do that with " +ob->GetShort()+".";
        }
        else if(wat){
            err = "It seems you can't do that to " +wat->GetShort()+".";
        }
        else {
            err = "It seems you can't do that.";
        }
        break;

        case ERR_IS_NOT:
        if(flag || (arg && stringp(arg))){
            if(flag || get_object(arg, this_player())){
                return "It appears you must be more specific.";
            }
            else if(arg && stringp(arg)) wut = remove_article(arg);
        }
        else wut = "that";
        err = capitalize(wut) +" is not here.";
        break;

        case ERR_NOT_LIVING:
        if( flag )
            err = "None of the " + pluralize(remove_article(arg)) +" are alive.";
        else err = "The " + remove_article(arg) + " is not alive.";
        break;

        case ERR_NOT_ACCESSIBLE:
        if( flag ) err = "You can't get to them.";
        else err = "You can't get to it.";
        break;

        case ERR_AMBIG:
        {
            mixed *obs;
            int i;
            gguy = this_player();
            if(DEFAULT_PARSING){
                gcmd = this_player()->GetLastCommand();
                this_player()->eventRetryCommand(gcmd, type, arg);
                return " ";
            }

            obs = unique_array(arg, (: $1->GetShort() :));
            if( sizeof(obs) == 1 )
                err = "Which of the " +
                    consolidate(sizeof(arg), obs[0][0]->GetShort()) +
                    " do you mean?";
            else {
                err = "Do you mean ";
                for(i = 0; i<sizeof(obs); i++) {
                    if( sizeof(obs[i]) > 1 )
                        err += "one of the " +
                            consolidate(sizeof(obs[i]),obs[i][0]->GetShort());
                    else err += obs[i][0]->GetShort();
                    if( i == (sizeof(obs)-2) ) err += " or ";
                    else if( i < sizeof(obs) - 1 ) err += ", ";
                }
                err += "?";
            }
            return err;
        }

        case ERR_ORDINAL:
        if( arg > 1 ) err = "There are only " + arg + " of them.";
        else err = "There is only one of them.";
        break;

        case ERR_ALLOCATED:
        return arg;

        case ERR_THERE_IS_NO:
        if(flag || (arg && stringp(arg)) && environment(this_player())){
            if(tmpob = present(arg, environment(this_player()))){
                return "It seems you must be more specific.";
            }
            else if(arg && stringp(arg)) wut = remove_article(arg);
        }
        else wut = "such thing";
        err = "There is no "+ wut +" here.";
        break;

        case ERR_BAD_MULTIPLE:
        err = "You can't do that to more than one at a time.";
        break;
    }
    return err;
}

void create_save() {
    string str;
    if(!stringp(str = previous_object()->GetKeyName())) return;
    if(file_size(DIR_PLAYERS+"/"+str[0..0]) == -2) return;
    if(str[0] < 'a' || str[0] > 'z') return;
    mkdir(DIR_PLAYERS+"/"+str[0..0]);
}

varargs object player_object(string nom, object stub) {
    object ob;
    string err, tmp;
    int old_limit;
    string sfilec = DIR_CRES+ "/" + nom[0..0]+ "/" +nom+__SAVE_EXTENSION__;
    string sfilep = DIR_PLAYERS+ "/" + nom[0..0]+ "/" +nom+__SAVE_EXTENSION__;
    tmp = base_name(ob = previous_object());
    if( tmp != CMD_ENCRE && tmp != CMD_DECRE && tmp != LIB_CONNECT 
            && tmp != RELOAD_D ){
        return 0;
    }
    old_limit = max_eval_cost();
    set_eval_limit(1000000000);
    if(tmp == RELOAD_D && stub) NewPlayer = stub;
    else NewPlayer = ob;
#if ENABLE_INSTANCES
    if(file_exists(new_savename(sfilec))){
        err = catch(ob = load_object(new_savename(sfilec)));
    }
    else{
        err = catch(ob = load_object(new_savename(sfilep)));
    }
#else
    if(ob == previous_object() && file_exists(sfilec)){
        string tmpy;
        if(last(sfilec,2) == ".o") tmpy = truncate(sfilec,2);
        ob = load_object(tmpy);
        if(!ob) ob = load_object(sfilec);
    }
    if(!ob || ob == previous_object()){
        string tmpy;
        if(last(sfilep,2) == ".o") tmpy = truncate(sfilep,2);
        ob = load_object(tmpy);
        if(!ob) ob = load_object(sfilep);
    }
#endif
    NewPlayer = 0;
    set_eval_limit(old_limit);
    if(err) error(err);
    return ob;
}

string player_save_file(string nom) { 
    string sfilec, sfilep;
    sfilec = DIR_CRES + "/" + nom[0..0] + "/" + nom + ".o";
    sfilep = DIR_PLAYERS + "/" + nom[0..0] + "/" + nom + ".o";
#if ENABLE_INSTANCES
    gstr = new_savename(sfilec);
    if(unguarded( (: file_exists, gstr :) )){ 
        return gstr;
    }
    return new_savename(sfilep);
#endif
    if(unguarded( (: file_exists, sfilec :) ) ){
        return sfilec;
    }
    return sfilep;
}

string *query_group(string grp) { return copy(Groups[grp]); }

mapping query_groups() { return copy(Groups); }

static void eventReset(){
    object *obs;
    object ob;
    int x, y;
    in_reset = 1;

    ResetNumber++;
    if(find_call_out("eventReset") == -1 && find_call_out(reset_handle) == -1){ 
        reset_handle = call_out( (: eventReset :), TIME_TO_RESET );
    }
    x = reclaim_objects();
    write_file(DIR_LOGS "/reset", "Reset " + ResetNumber + " occurred at: " +
            ctime(time()) + "\n");
    if(!RESET_ALL) obs = objects( (: !environment($1) && (random(100) < 26) :) );
    else obs = objects( (: !environment($1) :) );
    obs = filter(obs, (: !($1->GetNoClean()) :) );
    obs -= ({ this_object() });
    if(sizeof(obs) > 500){
        obs = scramble_array(obs)[0..500];
    }
    y = 0;
    foreach(ob in obs) {
        function f;
        if(ob){
            f = bind( (: call_other, ob, "clean_up" :), ob );
        }
        else {
            continue;
        }
        if( f ) catch(evaluate(f));
        if( !ob ) {
            y++;
            continue;
        }
        f = bind((: call_other, ob, "reset", ResetNumber :), ob);
        if( f ) catch(evaluate(f));
    }
    in_reset = 0;
    write_file(DIR_LOGS "/reset", "\t" + x + " objects reclaimed, " +
            (sizeof(obs) - y) + " objects reset, " + y + " objects "
            "cleaned.\n");
}

int RequestReset(){
    if(previous_object() && (base_name(previous_object()) == SEFUN 
                || base_name(previous_object()) == REAPER_D)){
        unguarded( (: eventReset :) );
        return 1;
    }
    return 0;
}

int GetResetNumber() { return ResetNumber; }

string *GetEfuns(){
    return (({})+ efuns_arr);
}

object *parse_command_users() {
    return filter(users(), (: creatorp($1) || $1->is_living() :));
}

int GetBootScore(){
    return BootScore;
}

int GetPerformanceScore(){
    if(!PerformanceScore){
        int ret, count = 1000;
        ret = time_expression {
            while(count){
                count--;
            }
        };
        PerformanceScore = ret;
    }
    return PerformanceScore;
}

int GetPerfOK(){
    if(!PerformanceScore) GetPerformanceScore();
    if(PerformanceScore <= MIN_PERF) return 1;
    return 0;
}

string GetMudName(){
    return MudName;
}

int SetMudName(string name){
    if(!valid_apply(({ "SECURE" }))){
        return 0;
    }
    MudName = name;
    return 1;
}

// MSSP
mapping get_mud_stats(){
    log_file("mssp", "\n"+timestamp()+" telopt mssp queried");
    return mssp_map();
}

mixed GetDreams(){
    return ({});
}

mixed eventPromise(){
    return false();
}

int ReadName(){
    string line_string, nameline, tmp;
    string *line_array;
    int port = query_host_port();
    MudName = "DeadSoulsNew";
    if(!find_object(INSTANCES_D) || !ENABLE_INSTANCES ||
            INSTANCES_D->GetMyInstanceName() == "global"){
        mconfig = "/secure/cfg/mudos.cfg";
    }
    else {
        mconfig = "/secure/cfg/mudos."+port+".cfg";
    }
    line_string = read_file(mconfig);
    if(!sizeof(line_string)){
        return 0;
    }
    line_array = explode(line_string, "\n");
    if(!sizeof(line_array)){
        return 0;
    }
    foreach(string line in line_array){
        if(!strsrch(line,"name :")){
            if(sscanf(line,"%*s : %s", tmp) < 2) {
                return 0;
            }
            MudName = tmp;
            return 1;
        }
    }
    return 0;
}