skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
/**
 * accesstool.c
 * The Access Control Tool
 * for the admtool
 * Shaydz 2 Apr '00
 */

#include <colors.h>
#include <access.h>

inherit COMMAND_BASE;

private mapping return_mapping = ([ ]);
private string main_menu_template = @END
-------------------------------------------------------------------------
%s
-------------------------------------------------------------------------
  %sCommand                                      Status%s

  [1]  Grant access to creator                 %s
  [2]  Revoke access from creator              %s
  [3]  List access                             %s

END;

private string main_prompt = "Enter your command [1-3], or [Q] to quit: ";
private string main_prompt2 = "Enter your command [1-3], [B] to go back, or [Q] to quit: ";

int cmd(string str);
private void get_command(string str);
private void add_creator(string str);
private void add_creator2(string str, string str2);
private void add_creator3(string path, string name, int mask);
private void revoke_creator(string str);
private void revoke_creator2(string str, string str2);
private void revoke_creator3(string path, string name, int mask);
string access_string(int access_flags);
private void do_summary(string str);
private string user_access(string);
private string list_access(string);

private void display_menu() {
    string title, s1, s2, s3;

    title = sprintf("%s%|72s%s", YELLOW, mud_name()+" Access Control Tool "
        "v1.5", RESET );

    s1 = s2 = s3 = RED+"Unavailable"+RESET;

    if( creatorp(TP) ) {
        s3 = GREEN+"Available"+RESET;
        s2 = s1 = MAGENTA+"Limited"+RESET;
    }

    if( adminp(TP) )
        s1 = s2 = s3 = GREEN+"Available"+RESET;

    tell_object( TP, sprintf( main_menu_template, title, BOLD, RESET,
        s1, s2, s3 ) );

} /* display_menu() */

private void do_prompt() {
    tell_object( TP, undefinedp(return_mapping[TP]) ? main_prompt :
                                                      main_prompt2 );
    input_to( (: get_command :) );
} /* do_prompt() */

private void add_creator( string str ) {
    if( !str || str == "")
        return do_prompt();

    if( !creatorp( str = lower_case(str) ) ) {
        tell_object( TP, RED+"\n"+CAP(str)+" is not a creator.\n"+RESET );
        return do_prompt();
    }

    tell_object( TP, "Enter the type of access to grant, "
        "(r)ead, (w)rite, (g)rant, [rwg]: ");

    input_to( (: add_creator2( $1, $(str) ) :) );

} /* add_creator() */

private void add_creator2( string str, string str2 ) {
    int mask;

    if( !str || str == "")
        return do_prompt();

    foreach( int flag in str ) {
        switch( flag ) {
          case 'r':
            mask |= READ_MASK;
          break;
          case 'w':
            mask |= WRITE_MASK;
          break;
          case 'g':
            if( !adminp(TP) ) {
                tell_object( TP, RED+"\nYou don't have permission to give "
                    "grant access."+RESET+"\n");
                return do_prompt();
            }
            mask |= GRANT_MASK;
          break;
          default:
            tell_object( TP, RED+"\n"+sprintf("Invalid access type - '%c'.\n",
                flag )+RESET );
            return do_prompt();
        }
    }

    if( mask < 1 ) {
        tell_object( TP, RED+"\nGrant cancelled.\n"+RESET );
        return do_prompt();
    }

    tell_object( TP, "Enter full directory path to give "+CAP(str2)+" access "
        "to (without the trailing /): ");
    input_to( (: add_creator3( $1, $(str2), $(mask) ) :) );

} /* add_creator2() */

private void add_creator3( string path, string name, int mask ) {
    string old;

    if( !path || path == "")
        return do_prompt();

    if( path != "/" && path[<1] == '/')
        path = path[0..<2];

    if( !dir_exists(path) ) {
        tell_object( TP, RED+"\nNo such directory: "+path+"\n"+RESET );
        return do_prompt();
    }

    old = geteuid(TO);
    seteuid(geteuid(TP));

    if( !master()->valid_grant( TP, path ) ||
        !master()->add_permission( name, path, mask ) ) {
        seteuid(old);
        tell_object( TP, RED+"\nYou do not have the privileges to grant access "
            "to "+path+".\n"+RESET );
        return do_prompt();
    }

    tell_object( TP, GREEN+"\n"+CAP(name)+" has been granted "+
        access_string(mask)+" access to "+path+"\n"+RESET );

    log_file("/secure/log/ACCESS", "%s granted <%s> access to %s for %s.\n",
        TP->query_cap_name(), access_string(mask), path, CAP(name) );

    return do_prompt();

} /* add_creator3() */

private void revoke_creator( string str ) {
    if( !str || str == "")
        return do_prompt();

    str = lower_case(str);

    tell_object( TP, "Enter the type of access to revoke, "
        "(r)ead, (w)rite, (g)rant, [rwg]: ");
    input_to( (: revoke_creator2( $1, $(str) ) :) );

} /* revoke_creator() */

private void revoke_creator2( string str, string str2 ) {
    int mask;

    if( !str || str == "")
        return do_prompt();

    foreach( int flag in str )
        switch( flag ) {
          case 'r':
            mask |= READ_MASK;
          break;
          case 'w':
            mask |= WRITE_MASK;
          break;
          case 'g':
            mask |= GRANT_MASK;
          break;
          default:
            tell_object( TP, RED+"\n"+sprintf("Invalid access type - '%c'.\n",
                flag )+RESET );
            return do_prompt();
        }

    if( mask < 1 ) {
        tell_object( TP, RED+"\nRevoke cancelled.\n"+RESET );
        return do_prompt();
    }

    tell_object( TP, "Enter full directory path to revoke access from "
        "(without the trailing /): ");
    input_to( (: revoke_creator3( $1, $(str2), $(mask) ) :) );

} /* revoke_creator2() */

private void revoke_creator3( string path, string name, int mask ) {
    string old;

    if( !path || path == "")
        return do_prompt();

    if( path != "/" && path[<1] == '/')
        path = path[0..<2];

    old = geteuid(TO);
    seteuid(geteuid(TP));

    if( !master()->valid_grant( TP, path ) ||
        !master()->remove_permission( name, path, mask ) ) {
        seteuid(old);
        tell_object( TP, RED+"\nYou do not have the privileges to revoke "
            "access to "+path+" from "+CAP(name)+".\n"+RESET );
        return do_prompt();
    }

    tell_object( TP, GREEN+ "\n"+access_string(mask)+" access to "+
        path+" has been revoked from "+CAP(name)+".\n"+RESET );
    log_file("/secure/log/ACCESS", "%s revoked <%s> access from %s to %s.\n",
        TP->query_cap_name(), access_string(mask), CAP(name), path );

    return do_prompt();

} /* revoke_creator3() */

/** @ignore yes */
string access_string( int access_flags ) {
    string plus = "";

    if( access_flags & READ_MASK )
        plus += "r";

    if( access_flags & WRITE_MASK )
        plus += "w";

    if( access_flags & GRANT_MASK )
        plus += "g";

    return plus;

} /* access_string() */

private void do_summary( string str ) {
    string ret;

    if( !str || str == "")
        ret = list_access(0);
    else if( dir_exists(str) )
        ret = list_access(str);
    else
        ret = user_access(str);

    if( ret )
        tell_object( TP, ret );

    return do_prompt();

} /* do_summary() */

private string user_access( string args ) {
    string ret = "", path, name, *paths, *names;
    mapping m = master()->query_permissions(), d = ([ ]);

    if( args ) {
        foreach( path in keys(m) )
            foreach( name in keys(m[path]) )
                if( name == args )
                    d[path] = "  "+sprintf("%-3s",
                        access_string(m[path][name]) )+" "+path+"\n";

        paths = sort_array( keys(d), 1 );

        foreach( path in paths )
            ret += d[path];

        if( ret == "") {
            if( !PLAYER_H->test_user(args) )
                return "No such player.\n";
            return CAP(args)+" has no access at this time.\n";
        } else {
            return ret;
        }
    }

    foreach( path in keys(m) )
        foreach( name in keys(m[path]) ) {
            if( undefinedp(d[name]) )
                d[name] = ({ });
            d[name] += ({ path });
        }

    names = sort_array( keys(d), 1 );

    foreach( name in names ) {
        ret += CAP(name)+":\n";
        paths = sort_array( d[name], 1 );

        foreach( path in paths )
            ret += "  "+sprintf("%-3s",
                access_string(m[path][name]))+" "+path+"\n";

        ret += "\n";
    }

    return ret;

} /* user_access() */

private string list_access( string args ) {
    mapping m = master()->query_permissions();
    string ret = "", *paths, *names;

    if( args ) {
        if( args[0] != '/')
            return args+": not a valid path.\n";

        if( args != "/" && args[<1] == '/')
            args = args[0..<2];

        if( undefinedp(m[args]) )
            return "No access has been granted for that path.\n";

        names = sort_array( keys(m[args]), 1 );
        ret = args +":\n";

        foreach( string name in names )
            ret += "  "+sprintf("%-3s",
                access_string(m[args][name]))+" "+CAP(name)+"\n";

        return ret;
    }

    // By sorting the paths into alphabetical order, that should imply
    // that access for /cmds is listed before access for /cmds/creator.
    paths = sort_array( keys(m), 1 );

    foreach( string path in paths ) {
        ret += path+":\n";

        names = sort_array( keys(m[path]), 1 );

        foreach( string name in names )
            ret += "  "+sprintf("%-3s",
                access_string(m[path][name]))+" "+CAP(name)+"\n";

        ret += "\n";
    }

    if( ret == "")
        return "No access has been granted to anyone at this time.\n";
    else
        return ret;

} /* list_access() */

private void get_command( string str ) {
    if( !str ) {
        display_menu();
        return do_prompt();
    }

    switch( str ) {
      case "1":
        tell_object( TP, "Enter the name of the creator to grant access to : ");
        input_to( (: add_creator :) );
      break;
      case "2":
        tell_object( TP, "Enter the name of the creator to revoke access from : ");
        input_to( (: revoke_creator :) );
      break;
      case "3":
        tell_object( TP, "Enter the name of the creator or a full path, "
            "(enter for the whole mud): ");
        input_to( (: do_summary :) );
      break;
      case "B":
      case "b":
        if( !return_mapping[TP] ) {
            display_menu();
            return do_prompt();
        }
        return_mapping[TP]->cmd("");
        map_delete( return_mapping, TP );
      break;
      case "Q":
      case "q":
        map_delete( return_mapping, TP );
        return;
      default:
        display_menu();
        return do_prompt();
    }
} /* get_command() */

/** @ignore yes */
int cmd( string arg ) {
    if( file_name(PO) == "/secure/cmds/creator/admtools")
        return_mapping[TP] = PO;

    display_menu();
    do_prompt();

    return 1;

} /* cmd() */