nightmare3_fluffos_v2/
nightmare3_fluffos_v2/bin/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/ChangeLog.old/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/Win32/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/simuls/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/clone/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/command/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/data/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/etc/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/master/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/log/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/compiler/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/efuns/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/operators/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/u/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/tmp/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/windows/
nightmare3_fluffos_v2/lib/cmds/ambassador/
nightmare3_fluffos_v2/lib/cmds/database/
nightmare3_fluffos_v2/lib/cmds/hm/
nightmare3_fluffos_v2/lib/cmds/soul/
nightmare3_fluffos_v2/lib/daemon/cfg/
nightmare3_fluffos_v2/lib/daemon/cfg/mon_races/
nightmare3_fluffos_v2/lib/daemon/cfg/races/
nightmare3_fluffos_v2/lib/daemon/include/
nightmare3_fluffos_v2/lib/daemon/save/
nightmare3_fluffos_v2/lib/daemon/services/
nightmare3_fluffos_v2/lib/daemon/soul/
nightmare3_fluffos_v2/lib/doc/
nightmare3_fluffos_v2/lib/doc/TestPlans/
nightmare3_fluffos_v2/lib/doc/approval/
nightmare3_fluffos_v2/lib/doc/approval/QC/
nightmare3_fluffos_v2/lib/doc/approval/balance/
nightmare3_fluffos_v2/lib/doc/build/
nightmare3_fluffos_v2/lib/doc/build/armours/
nightmare3_fluffos_v2/lib/doc/build/economy/
nightmare3_fluffos_v2/lib/doc/build/etc/
nightmare3_fluffos_v2/lib/doc/build/monster/
nightmare3_fluffos_v2/lib/doc/build/room/
nightmare3_fluffos_v2/lib/doc/build/virtual/
nightmare3_fluffos_v2/lib/doc/build/weapon/
nightmare3_fluffos_v2/lib/doc/classes/
nightmare3_fluffos_v2/lib/doc/efun/
nightmare3_fluffos_v2/lib/doc/etc/
nightmare3_fluffos_v2/lib/doc/help/creator/
nightmare3_fluffos_v2/lib/doc/help/hm/
nightmare3_fluffos_v2/lib/doc/law/
nightmare3_fluffos_v2/lib/doc/lpc/basic/
nightmare3_fluffos_v2/lib/doc/lpc/data_types/
nightmare3_fluffos_v2/lib/doc/lpc/etc/
nightmare3_fluffos_v2/lib/doc/lpc/intermediate/
nightmare3_fluffos_v2/lib/doc/lpc/types/
nightmare3_fluffos_v2/lib/doc/mudlib/
nightmare3_fluffos_v2/lib/doc/mudlib/features/
nightmare3_fluffos_v2/lib/domains/Examples/etc/
nightmare3_fluffos_v2/lib/domains/Examples/room/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaA/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaB/
nightmare3_fluffos_v2/lib/domains/Examples/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/
nightmare3_fluffos_v2/lib/domains/Praxis/adm/
nightmare3_fluffos_v2/lib/domains/Praxis/attic/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/mon/
nightmare3_fluffos_v2/lib/domains/Praxis/data/
nightmare3_fluffos_v2/lib/domains/Praxis/death/
nightmare3_fluffos_v2/lib/domains/Praxis/mountains/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/armour/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/magic/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/orc_valley/
nightmare3_fluffos_v2/lib/domains/Praxis/quests/
nightmare3_fluffos_v2/lib/domains/Praxis/standardOld/
nightmare3_fluffos_v2/lib/include/
nightmare3_fluffos_v2/lib/log/
nightmare3_fluffos_v2/lib/log/errors/
nightmare3_fluffos_v2/lib/log/reports/
nightmare3_fluffos_v2/lib/log/watch/
nightmare3_fluffos_v2/lib/news/
nightmare3_fluffos_v2/lib/secure/cfg/
nightmare3_fluffos_v2/lib/secure/cmds/ambassador/
nightmare3_fluffos_v2/lib/secure/cmds/mortal/
nightmare3_fluffos_v2/lib/secure/save/users/d/
nightmare3_fluffos_v2/lib/secure/std/
nightmare3_fluffos_v2/lib/std/hm/
nightmare3_fluffos_v2/lib/std/living/
nightmare3_fluffos_v2/lib/std/room/
nightmare3_fluffos_v2/lib/std/user/
nightmare3_fluffos_v2/lib/std/virtual/
nightmare3_fluffos_v2/lib/www/
nightmare3_fluffos_v2/lib/www/errors/
nightmare3_fluffos_v2/lib/www/gateways/
nightmare3_fluffos_v2/win32/
/*    /adm/obj/master.c
 *    from Nightmare 3.3
 *    the master object, responsible for security
 *    created by Descartes of Borg 940910
 *    error handling by Beek@The Idea Exchange 941004
 */

#include <config.h>
#include <objects.h>
#include <rooms.h>
#include <cfg.h>
#include <privs.h>
#include <dirs.h>
#include <save.h>
#include <daemons.h>
#include "master.h"

static private object __Unguarded;
static private string __PlayerName;
static private object __NewPlayer;
static private mapping __Groups, __ReadAccess, __WriteAccess;

void create() {
    __Unguarded = 0;
    __NewPlayer = 0;
    __PlayerName = 0;
    new_read();
    new_write();
    new_groups();
}

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;
}

static private void load_access(string cfg, mapping ref) {
    string *lines;
    string file, fl, ac;
    int i, maxi;

    if(!(file = read_file(cfg)))
      error("Failed to find config file: "+cfg);
    maxi = sizeof(lines = explode(file, "\n"));
    for(i=0; i<maxi; i++) {
        if(!lines[i] || lines[i] == "" || lines[i][0] == '#') continue;
        if(sscanf(lines[i], "(%s) %s", fl, ac) != 2)
          error("Error in loading config file "+cfg+" at line "+
            (i+1));
        ref[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 "+(string)call_other(file, arg)+" back.\n");
        return;
    }
    write("Master: unknown flag.\n");
}

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

    call_out("socket_preload", 5);
    if(!(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 base;
    int ext;

    sscanf(file, "%s#%d", base, ext);
    if("/"+base == OB_USER) {
        string *grps;
        string str;
        int i;

        if(!__PlayerName) return 0;
        str = __PlayerName;
        i = sizeof(grps = keys(__Groups));
        while(i--)
          if(member_array(__PlayerName, __Groups[grps[i]]) != -1)
            str = str + ":" + grps[i];
        return str;
    }
    return file_privs(file);
}

void preload(string str) {
    string err;
    int t;

    if(!file_exists(str+".c")) return;
    t = time();
    write("Preloading: "+str+"...");
    if(err=catch(call_other(str, "???")))
      write("\nGot error "+err+" when loading "+str+".\n");
    else {
        t = time() - t;
        write("("+(t/60)+"."+(t%60)+")\n");
    }
}

void socket_preload() {
    string *items;
    int i, max;

    max = sizeof(items=explode(read_file(CFG_PRELOAD_SOCKET), "\n"));
    for(i=0; i<max; i++) {
        if(!items[i] || items[i] == "" || items[i][0] == '#') continue;
        catch(call_other(items[i], "???"));
    }
}

int valid_write(string file, object ob, string fun) {
    string *ok;

    if(ob == master()) return 1;
    if(file[0] != '/') file = "/"+file;
    if(!(ok = match_path(__WriteAccess, file))) ok = 0;
    if(check_access(ob, fun, file, ok, "write")) return 1;
    log_file("access", "Write access denied: "+file+" : "+
      identify(previous_object(-1))+" : "+fun+"\n");
    return 0;
}

int valid_read(string file, object ob, string fun) {
    string *ok;
    if(ob == master()) return 1;
    if(file[0] != '/') file = "/"+file;
    if(!(ok = match_path(__ReadAccess, file))) ok = 0;

    //tc("\n-------");
    //tc("valid_read("+identify(file)+", "+identify(ob)+", "+identify(fun)+")");
    //tc("match_path(__ReadAccess, "+identify(file)+"): "+identify(ok));
    //tc("check_access: "+check_access(ob, fun, file, ok, "read"));
    //tc("-----------\n");

    if(check_access(ob, fun, file, ok, "read")) return 1;
    log_file("access", "Read access denied: "+file+" : "+
      identify(previous_object(-1))+" : "+fun+"\n");
    return 0;
}

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

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

    if(objectp(file)) file = base_name(file);
    if(ok && sizeof(ok) && ok[0] == "all") return 1;
    if(__Unguarded == ob) {
        string tmp;

        if((tmp = base_name(ob)) == OB_USER) {
            //debug_message("master(): checking "+file+" access for "+__PlayerName);
            if(!__PlayerName) i = sizeof(stack = ({ob})+previous_object(-1));
            else if(file == DIR_USERS+"/"+__PlayerName[0..0]+"/"+__PlayerName+__SAVE_EXTENSION__)
              return 1;
            else i = sizeof(stack = ({ ob }));
        }
        else if(tmp == file) return 1;
        else i = sizeof(stack = ({ ob }));
    }
    else if(__Unguarded && base_name(ob) == OB_SIMUL_EFUN) {
        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]) == OB_SIMUL_EFUN) continue;
        if(!(priv = query_privs(stack[i]))) return 0;
        if(!ok && oper == "read") continue;
        privs = explode(priv, ":");
        if(member_array(PRIV_SECURE, privs) != -1) continue;
        if(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 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;
    int x;

    if(!sscanf(file, REALMS_DIRS+"/%s/%*s", nom)) return 0;
    nom = user_path(nom)+"adm/access";
    if(file_size(nom+".c") < 0) return 0;
    catch(x = (int)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 = (int)call_other(nom, "check_access", ob, fun, file, o));
    return x;
}

object connect() {
    object ob;
    string err;

    if(err=catch(ob = clone_object(OB_LOGIN))) {
        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;
    object ob;
    //debug_message("master(): compile_object(\""+str+"\")");
    if(sscanf(str, REALMS_DIRS+"/%s/%*s", nom)){
      //debug_message("alpha");
      tmp = sprintf("%svirtual/server", user_path(nom));
    }
    else if(sscanf(str, DOMAINS_DIRS+"/%s/%*s", nom)){
      //debug_message("bravo");
      tmp = sprintf("%s/%s/virtual/server", DOMAINS_DIRS, nom);
    }
    else if(strsrch(str, ESTATES_DIRS) == 0){
      //debug_message("charlie");
      tmp = sprintf("%s/adm/server", ESTATES_DIRS);
    }
    else if(sscanf(str, DIR_USERS+"/%*s/%s", nom)) {
        //debug_message("yoohoo!");
        if(!__NewPlayer) return 0;
        //debug_message("over here!");
        if((string)__NewPlayer->query_name() != nom) return 0;
        //debug_message("hi sailor!");
        __PlayerName = nom;
        ob = new(OB_USER);
        //debug_message("master() str: "+str);
        if(file_exists(str+__SAVE_EXTENSION__)) ob->restore_player(nom);
        else if(file_size(DIR_USERS) != -2) mkdir(DIR_USERS);
        else if(file_size(DIR_USERS+"/"+nom[0..0]) != -2)
          mkdir(DIR_USERS+"/"+nom[0..0]);
        ob->set_name(nom);
        __PlayerName = 0;
        //debug_message("master() ob: "+identify(ob));
        return ob;
    }
    else {
       //debug_message("delta");
    }
    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 (object)call_other(tmp, "compile_object", where);
    }
    return (object)call_other(tmp, "compile_object", str);                      
}

static void crash(string err) {
    write_file(DIR_LOGS+"/crashes", mud_name()+" crashed "+ctime(time())+" with error "+
      err+".\n");
    shout("Atmos tells you think "+mud_name()+" is crashing!\n");
    shout("Atmos forced you to: quit\n");
    users()->force_me("quit");
}

int valid_seteuid(object ob, string id) {
    string fn, uid;

return 1;
    if((uid = getuid(ob)) == id) return 1;
    if(uid == "Root") return 1;
    if(file_name(ob) == OB_SIMUL_EFUN) return 1;
    if(uid == "System" && id != "Root" && id != "Backbone")
      return 1;
    return 0;
}

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 == OB_SIMUL_EFUN || file == "/secure/SimulEfun/overrides");
}

int valid_socket(object ob, string fun, mixed *info) {
    object *obs;
    string tmp;
    int i;

    i = sizeof(obs = previous_object(-1));
    while(i--) {
        if(!obs[i]) continue;
        if(userp(obs[i])) continue;
        if(!(tmp = query_privs(obs[i]))) return 0;
        if(!sizeof(explode(tmp,":") & ({ PRIV_SECURE,PRIV_MUDLIB}))) return 0;
    }
    return 1;
}

int valid_function(function f) { return 1; }

string get_wiz_name(string file) {
    string nom, dir, tmp;

    if(file[0] != '/') file = "/"+file;
    if(sscanf(file, REALMS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    if(sscanf(file, DOMAINS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    sscanf(file, "/%s/%s", nom, tmp);
    return nom;
}

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

    if(base_name(previous_object(0)) != OB_SIMUL_EFUN) {
        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;

    ret = "---\n"+standard_trace(mp);
    if (caught) {
        write_file("/log/catch", ret);
    } else {
        write_file("/log/runtime", ret);
    }
    if (this_player(1)) {
        tell_object(this_player(1), sprintf("%sTrace written to /log/%s\n", mp["error"], (caught ? "catch" : "runtime")));
        this_player(1)->set_error(mp);
    }
    return 0;
}

void log_error(string file, string msg) {
    string nom, home;

    if(this_player(1) && (find_object(OB_SIMUL_EFUN) && creatorp(this_player(1))))
      message("error", msg, this_player(1));
    if(!(nom = get_wiz_name(file))) nom = "log";
    catch(write_file(DIR_ERROR_LOGS+"/"+nom, msg));
}

varargs string standard_trace(mapping mp, int flag) {
    string obj, 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()) != OB_SIMUL_EFUN) return;
    if(file_size(file) > MAX_LOG_SIZE) rename(file, file+".old");
    write_file(file, msg);
}

void destruct_env_of(object ob) {
    if(!interactive(ob)) return;
    message("environment", "Whoop whoop whoop.... BOOM!!!  And now "
      "nothing exists any longer!", ob);
    ob->move(ROOM_VOID);
}

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

int player_exists(string str) {
    if(!str) return 0;
    str = DIR_USERS+"/"+str[0..0]+"/"+str+__SAVE_EXTENSION__;
    return (file_size(str) > -1);
}

string get_root_uid() { return "Root"; }

string get_bb_uid() { return "Backbone"; }

string creator_file(string str) {
    string base;
    int ext;

    sscanf(str, "%s#%d", base, ext);
    if("/"+base == OB_USER)
      return (__PlayerName ? __PlayerName : "Mudlib");
    return (string)call_other(OB_SIMUL_EFUN, "creator_file", str);
}

string domain_file(string str) {
    string nom, tmp;

    if(str[0] != '/') str = "/"+str;
    if(sscanf(str, DOMAINS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    return 0;
}

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

    if(str[0] != '/') str = "/"+str;
    if(sscanf(str, REALMS_DIRS+"/%s/%s", nom, tmp) == 2) return nom;
    return 0;
}

static int slow_shutdown() {
    write_file(DIR_LOGS+"/game_log", "Armageddon loaded by master: "+ctime(time())+".\n");
    new(OB_SHUT)->move(ROOM_START);
    SHUT_D->reboot_mud(4);
    return 1;
}

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

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

int retrieve_ed_setup(object who) {
    string file;
    int x;

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

string get_save_file_name(string file) {
    string str;

    str = (string)this_player()->query_name();
    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",
      "from", "between", "at", "to", "over", "near" });
}

string parse_command_all_word() { return "all"; }

void create_save() {
    string str;

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

object player_object(string nom) {
    object ob;
    string err;
    string pfile = DIR_USERS+"/"+nom[0..0]+"/"+nom;

    //debug_message("1");
    if(base_name(ob = previous_object(0)) != OB_LOGIN) return 0;
    //debug_message("2");
    set_eval_limit(1000000000);
    __NewPlayer = ob;
    //mkdir(DIR_USERS+"/"+nom[0..0]);
    //if(file_size(pfile) == -1) write_file(pfile,"");
    //debug_message("master() about to try loading: "+pfile);
    err = catch(ob = load_object(pfile));
    __NewPlayer = 0;
    set_eval_limit(-1);
    if(err){
    //debug_message("error: "+err);
    error(err);
    }
    //if(!ob) ob = new("/std/user");
    //if(!ob) ob = ;
    return ob;
}

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

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